Files
Charon/docs/guides/dns-providers/google-cloud-dns.md
GitHub Actions 3169b05156 fix: skip incomplete system log viewer tests
- Marked 12 tests as skip pending feature implementation
- Features tracked in GitHub issue #686 (system log viewer feature completion)
- Tests cover sorting by timestamp/level/method/URI/status, pagination controls, filtering by text/level, download functionality
- Unblocks Phase 2 at 91.7% pass rate to proceed to Phase 3 security enforcement validation
- TODO comments in code reference GitHub #686 for feature completion tracking
- Tests skipped: Pagination (3), Search/Filter (2), Download (2), Sorting (1), Log Display (4)
2026-02-09 21:55:55 +00:00

11 KiB

# Google Cloud DNS Provider Setup

## Overview

Google Cloud DNS is a high-performance, scalable DNS service built on Google's global infrastructure. This guide covers setting up Google Cloud DNS as a provider in Charon for wildcard certificate management.

## Prerequisites

- Google Cloud Platform (GCP) account
- GCP project with billing enabled
- Cloud DNS API enabled
- DNS zone created in Cloud DNS
- Domain nameservers pointing to Google Cloud DNS

## Step 1: Enable Cloud DNS API

1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Select your project (or create a new one)
3. Navigate to **APIs & Services****Library**
4. Search for **Cloud DNS API**
5. Click **Enable**

> **Note:** The API may take a few minutes to activate after enabling.

## Step 2: Create a Service Account

Create a dedicated service account for Charon with minimal permissions:

1. Navigate to **IAM & Admin****Service Accounts**
2. Click **Create Service Account**
3. Configure the service account:
   - **Service account name:** `charon-dns-challenge`
   - **Service account ID:** `charon-dns-challenge` (auto-filled)
   - **Description:** `Service account for Charon DNS-01 ACME challenges`
4. Click **Create and Continue**

## Step 3: Assign DNS Admin Role

1. In the **Grant this service account access to project** section:
   - Click **Select a role**
   - Search for **DNS Administrator**
   - Select **DNS Administrator** (`roles/dns.admin`)
2. Click **Continue**
3. Skip the optional **Grant users access** section
4. Click **Done**

> **Security Note:** For production environments, consider creating a custom role with only the specific permissions needed:
> - `dns.changes.create`
> - `dns.changes.get`
> - `dns.managedZones.list`
> - `dns.resourceRecordSets.create`
> - `dns.resourceRecordSets.delete`
> - `dns.resourceRecordSets.list`
> - `dns.resourceRecordSets.update`

## Step 4: Generate Service Account Key

1. Click on the newly created service account
2. Navigate to the **Keys** tab
3. Click **Add Key****Create new key**
4. Select **JSON** format
5. Click **Create**
6. **Save the downloaded JSON file securely** (shown only once)

> **Warning:** The JSON key file contains sensitive credentials. Store it in a password manager or secure vault. Never commit it to version control.

### Example JSON Key Structure

```json
{
  "type": "service_account",
  "project_id": "your-project-id",
  "private_key_id": "key-id",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "charon-dns-challenge@your-project-id.iam.gserviceaccount.com",
  "client_id": "123456789012345678901",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
}
```

## Step 5: Verify DNS Zone Configuration

Ensure your domain is properly configured in Cloud DNS:

1. Navigate to **Network services****Cloud DNS**
2. Verify your zone is listed and active
3. Note the **Zone name** (not the DNS name)
4. Confirm nameservers are correctly assigned:
   - `ns-cloud-a1.googledomains.com`
   - `ns-cloud-a2.googledomains.com`
   - `ns-cloud-a3.googledomains.com`
   - `ns-cloud-a4.googledomains.com`

> **Important:** Update your domain registrar to use Google Cloud DNS nameservers if not already configured.

## Step 6: Configure in Charon

1. Navigate to **DNS Providers** in Charon
2. Click **Add Provider**
3. Fill in the form:
   - **Provider Type:** Select `Google Cloud DNS`
   - **Name:** Enter a descriptive name (e.g., "GCP Cloud DNS - Production")
   - **Project ID:** Enter your GCP project ID (e.g., `my-project-123456`)
   - **Service Account JSON:** Paste the entire contents of the downloaded JSON key file

### Advanced Settings (Optional)

Expand **Advanced Settings** to customize:

- **Propagation Timeout:** `120` seconds (Cloud DNS propagation is typically fast)
- **Polling Interval:** `10` seconds (default)
- **Set as Default:** Enable if this is your primary DNS provider

## Step 7: Test Connection

1. Click **Test Connection** button
2. Wait for validation (usually 5-10 seconds)
3. Verify you see: ✅ **Connection successful**

The test verifies:
- Service account credentials are valid
- Project ID matches the credentials
- Service account has required permissions
- Cloud DNS API is accessible

If the test fails, see [Troubleshooting](#troubleshooting) below.

## Step 8: Save Configuration

Click **Save** to store the DNS provider configuration. Credentials are encrypted at rest using AES-256-GCM.

## Step 9: Use with Wildcard Certificates

When creating a proxy host with a wildcard domain:

1. Navigate to **Proxy Hosts****Add Proxy Host**
2. Enter a wildcard domain: `*.example.com`
3. Select **Google Cloud DNS** from the DNS Provider dropdown
4. Configure remaining settings
5. Save

Charon will automatically obtain a wildcard certificate using DNS-01 challenge.

## Example Configuration

```yaml
Provider Type: googleclouddns
Name: GCP Cloud DNS - example.com
Project ID: my-project-123456
Service Account JSON: {"type":"service_account",...}
Propagation Timeout: 120 seconds
Polling Interval: 10 seconds
Default: Yes
```

## Required Permissions

The service account needs the following Cloud DNS permissions:

| Permission | Purpose |
|------------|---------|
| `dns.changes.create` | Create DNS record changes |
| `dns.changes.get` | Check status of DNS changes |
| `dns.managedZones.list` | List available DNS zones |
| `dns.resourceRecordSets.create` | Create TXT records for ACME challenges |
| `dns.resourceRecordSets.delete` | Clean up TXT records after validation |
| `dns.resourceRecordSets.list` | List existing DNS records |
| `dns.resourceRecordSets.update` | Update DNS records if needed |

> **Note:** The **DNS Administrator** role includes all these permissions. For fine-grained control, create a custom role.

## Troubleshooting

### Connection Test Fails

**Error:** `Invalid service account JSON`

- Verify the entire JSON content was pasted correctly
- Ensure no extra whitespace or line breaks were added
- Check the JSON is valid (use a JSON validator)
- Re-download the key file and try again

**Error:** `Project not found` or `Project mismatch`

- Verify the Project ID matches the project in the service account JSON
- Check the `project_id` field in the JSON matches your input
- Ensure the project exists and is active

**Error:** `Permission denied` or `Forbidden`

- Verify the service account has the DNS Administrator role
- Check the role is assigned at the project level
- Ensure Cloud DNS API is enabled
- Wait a few minutes after role assignment (propagation delay)

**Error:** `API not enabled`

- Navigate to APIs & Services → Library
- Search for and enable Cloud DNS API
- Wait 2-3 minutes for activation

### Certificate Issuance Fails

**Error:** `DNS propagation timeout`

- Cloud DNS typically propagates in 30-60 seconds
- Increase Propagation Timeout to 180 seconds
- Verify nameservers are correctly configured with your registrar
- Check Google Cloud Status page for service issues

**Error:** `Zone not found`

- Ensure the DNS zone exists in Cloud DNS
- Verify the domain matches the zone's DNS name
- Check the service account has access to the zone

**Error:** `Record creation failed`

- Check for existing `_acme-challenge` TXT records that may conflict
- Verify service account permissions
- Review Charon logs for detailed API errors

### Nameserver Propagation

**Issue:** DNS changes not visible globally

- Nameserver changes can take 24-48 hours to propagate globally
- Use [DNS Checker](https://dnschecker.org/) to verify propagation
- Verify your registrar shows Google Cloud DNS nameservers
- Wait for full propagation before attempting certificate issuance

### Rate Limiting

Google Cloud DNS API quotas:

- 10,000 queries per day (default)
- 1,000 changes per day (default)
- Certificate challenges typically use <20 requests

If you hit limits:

- Request quota increase via Google Cloud Console
- Reduce frequency of certificate renewals
- Contact Google Cloud support for production workloads

## Security Recommendations

1. **Dedicated Service Account:** Create a separate service account for Charon
2. **Least Privilege:** Use a custom role with only required permissions
3. **Key Rotation:** Rotate service account keys every 90 days
4. **Key Security:** Store JSON key in a secrets manager, never in version control
5. **Audit Logging:** Enable Cloud Audit Logs for DNS API calls
6. **VPC Service Controls:** Consider using VPC Service Controls for additional security
7. **Disable Unused Keys:** Delete old keys immediately after rotation

## Service Account Key Rotation

To rotate the service account key:

1. Create a new key following Step 4
2. Update the configuration in Charon with the new JSON
3. Test the connection to verify the new key works
4. Delete the old key from the GCP console

```bash
# Using gcloud CLI (optional)
# List existing keys
gcloud iam service-accounts keys list \
  --iam-account=charon-dns-challenge@PROJECT_ID.iam.gserviceaccount.com

# Create new key
gcloud iam service-accounts keys create new-key.json \
  --iam-account=charon-dns-challenge@PROJECT_ID.iam.gserviceaccount.com

# Delete old key (after updating Charon)
gcloud iam service-accounts keys delete KEY_ID \
  --iam-account=charon-dns-challenge@PROJECT_ID.iam.gserviceaccount.com
```

## gcloud CLI Verification (Optional)

Test credentials before adding to Charon:

```bash
# Activate service account
gcloud auth activate-service-account \
  --key-file=/path/to/service-account-key.json

# Set project
gcloud config set project YOUR_PROJECT_ID

# List DNS zones
gcloud dns managed-zones list

# Test record creation (creates and deletes a test TXT record)
gcloud dns record-sets create test-acme-challenge.example.com. \
  --zone=your-zone-name \
  --type=TXT \
  --ttl=60 \
  --rrdatas='"test-value"'

# Clean up test record
gcloud dns record-sets delete test-acme-challenge.example.com. \
  --zone=your-zone-name \
  --type=TXT
```

## Additional Resources

- [Google Cloud DNS Documentation](https://cloud.google.com/dns/docs)
- [Service Account Documentation](https://cloud.google.com/iam/docs/service-accounts)
- [Cloud DNS API Reference](https://cloud.google.com/dns/docs/reference/v1)
- [Caddy Google Cloud DNS Module](https://caddyserver.com/docs/modules/dns.providers.googleclouddns)
- [Google Cloud Status Page](https://status.cloud.google.com/)
- [IAM Roles for Cloud DNS](https://cloud.google.com/dns/docs/access-control)

## Related Documentation

- [DNS Providers Overview](../dns-providers.md)
- [Wildcard Certificates Guide](../certificates.md#wildcard-certificates)
- [DNS Challenges Troubleshooting](../../troubleshooting/dns-challenges.md)