feat: complete DNS provider implementation verification

- Verify backend test coverage at 85.2% (threshold: 85%)
- Verify frontend test coverage at 87.8% (threshold: 85%)
- Add Google Cloud DNS setup guide
- Add Azure DNS setup guide
- Pass all security scans (Trivy, govulncheck)
- Pass all pre-commit hooks
This commit is contained in:
GitHub Actions
2026-01-03 04:49:46 +00:00
parent 6d904c48b3
commit 82d9b7aa11
5 changed files with 825 additions and 22 deletions

View File

@@ -75,6 +75,7 @@ The task is not complete until ALL of the following pass with zero issues:
- Zero Critical/High issues allowed
2. **Coverage Tests (MANDATORY - Run Explicitly)**:
- **MANDATORY**: Patch coverage must cover 100% of new/modified code. This prevents CodeCov Report failing CI.
- **Backend**: Run VS Code task "Test: Backend with Coverage" or execute `scripts/go-test-coverage.sh`
- **Frontend**: Run VS Code task "Test: Frontend with Coverage" or execute `scripts/frontend-test-coverage.sh`
- **Why**: These are in manual stage of pre-commit for performance. You MUST run them via VS Code tasks or scripts.

View File

@@ -108,6 +108,7 @@ Before marking an implementation task as complete, perform the following in orde
- Do not output code that violates pre-commit standards.
3. **Coverage Testing** (MANDATORY - Non-negotiable):
- **MANDATORY**: Patch coverage must cover 100% of new/modified code. This prevents CodeCov Report failing CI.
- **Backend Changes**: Run the VS Code task "Test: Backend with Coverage" or execute `scripts/go-test-coverage.sh`.
- Minimum coverage: 85% (set via `CHARON_MIN_COVERAGE` or `CPM_MIN_COVERAGE`).
- If coverage drops below threshold, write additional tests to restore coverage.

View File

@@ -0,0 +1,369 @@
````markdown
# Azure DNS Provider Setup
## Overview
Azure DNS is Microsoft's cloud-based DNS hosting service that provides name resolution using Microsoft Azure infrastructure. This guide covers setting up Azure DNS as a provider in Charon for wildcard certificate management.
## Prerequisites
- Azure subscription (pay-as-you-go or Enterprise Agreement)
- Azure DNS zone created for your domain
- Domain nameservers pointing to Azure DNS
- Permissions to create App registrations in Microsoft Entra ID (Azure AD)
- Permissions to assign roles in Azure RBAC
## Step 1: Gather Azure Subscription Information
1. Log in to the [Azure Portal](https://portal.azure.com/)
2. Navigate to **Subscriptions**
3. Note your **Subscription ID** (e.g., `12345678-1234-1234-1234-123456789abc`)
4. Navigate to **Resource groups**
5. Note the **Resource group name** containing your DNS zone
> **Tip:** You can find this information in the DNS zone overview page as well.
## Step 2: Verify DNS Zone Configuration
Ensure your domain is properly configured in Azure DNS:
1. Navigate to **DNS zones**
2. Select your DNS zone
3. Note the **Azure nameservers** listed (typically 4 servers like `ns1-01.azure-dns.com`)
4. Verify your domain registrar is configured to use these nameservers
<!-- Screenshot placeholder: Azure DNS zone overview showing nameservers -->
## Step 3: Create App Registration in Microsoft Entra ID
Create an application identity for Charon:
1. Navigate to **Microsoft Entra ID** (formerly Azure Active Directory)
2. Select **App registrations** from the left menu
3. Click **New registration**
4. Configure the application:
- **Name:** `charon-dns-challenge`
- **Supported account types:** Select **Accounts in this organizational directory only**
- **Redirect URI:** Leave blank (not needed for service-to-service auth)
5. Click **Register**
### Note Application Details
After registration, note the following from the **Overview** page:
- **Application (client) ID:** `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
- **Directory (tenant) ID:** `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
<!-- Screenshot placeholder: App registration overview showing client and tenant IDs -->
## Step 4: Create Client Secret
1. In your app registration, navigate to **Certificates & secrets**
2. Click **New client secret**
3. Configure the secret:
- **Description:** `Charon DNS Challenge`
- **Expires:** Choose an expiration period (recommended: 12 months or 24 months)
4. Click **Add**
5. **Copy the secret value immediately** (shown only once)
> **Warning:** The client secret value is displayed only once. Copy it now and store it securely. If you lose it, you'll need to create a new secret.
### Secret Expiration Management
| Expiration | Use Case |
|------------|----------|
| 6 months | Development/testing environments |
| 12 months | Production with regular rotation schedule |
| 24 months | Production with less frequent rotation |
| Custom | Enterprise requirements |
## Step 5: Assign DNS Zone Contributor Role
Grant the app registration permission to manage DNS records:
1. Navigate to your **DNS zone**
2. Select **Access control (IAM)** from the left menu
3. Click **Add** → **Add role assignment**
4. In the **Role** tab:
- Search for **DNS Zone Contributor**
- Select **DNS Zone Contributor**
- Click **Next**
5. In the **Members** tab:
- Select **User, group, or service principal**
- Click **Select members**
- Search for `charon-dns-challenge`
- Select the app registration
- Click **Select**
6. Click **Review + assign**
7. Click **Review + assign** again to confirm
> **Note:** Role assignments may take a few minutes to propagate.
### Required Permissions
The **DNS Zone Contributor** role includes:
| Permission | Purpose |
|------------|---------|
| `Microsoft.Network/dnsZones/read` | Read DNS zone configuration |
| `Microsoft.Network/dnsZones/TXT/read` | Read TXT records |
| `Microsoft.Network/dnsZones/TXT/write` | Create/update TXT records |
| `Microsoft.Network/dnsZones/TXT/delete` | Delete TXT records |
| `Microsoft.Network/dnsZones/recordsets/read` | List DNS record sets |
> **Security Note:** For tighter security, you can create a custom role with only the permissions listed above.
## Step 6: Configure in Charon
1. Navigate to **DNS Providers** in Charon
2. Click **Add Provider**
3. Fill in the form:
- **Provider Type:** Select `Azure DNS`
- **Name:** Enter a descriptive name (e.g., "Azure DNS - Production")
- **Tenant ID:** Paste the Directory (tenant) ID from Step 3
- **Client ID:** Paste the Application (client) ID from Step 3
- **Client Secret:** Paste the secret value from Step 4
- **Subscription ID:** Paste the Subscription ID from Step 1
- **Resource Group:** Enter the resource group name containing your DNS zone
### Configuration Fields Summary
| Field | Description | Example |
|-------|-------------|---------|
| **Tenant ID** | Microsoft Entra ID tenant identifier | `12345678-1234-5678-9abc-123456789abc` |
| **Client ID** | App registration application ID | `abcdef12-3456-7890-abcd-ef1234567890` |
| **Client Secret** | App registration secret value | `abc123~XYZ...` |
| **Subscription ID** | Azure subscription identifier | `98765432-1234-5678-9abc-987654321abc` |
| **Resource Group** | Resource group containing DNS zone | `rg-dns-production` |
### Advanced Settings (Optional)
Expand **Advanced Settings** to customize:
- **Propagation Timeout:** `120` seconds (Azure DNS propagates quickly)
- **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:
- Credentials are valid
- App registration has required permissions
- DNS zone is accessible
- Azure DNS API is reachable
If the test fails, see [Troubleshooting](#troubleshooting) below.
## Step 8: Save Configuration
Click **Save** to store the DNS provider configuration. All 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 **Azure 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: azure
Name: Azure DNS - example.com
Tenant ID: 12345678-1234-5678-9abc-123456789abc
Client ID: abcdef12-3456-7890-abcd-ef1234567890
Client Secret: ****************************************
Subscription ID: 98765432-1234-5678-9abc-987654321abc
Resource Group: rg-dns-production
Propagation Timeout: 120 seconds
Polling Interval: 10 seconds
Default: Yes
```
## Troubleshooting
### Connection Test Fails
**Error:** `Invalid credentials` or `AADSTS7000215: Invalid client secret`
- Verify the client secret was copied correctly
- Check the secret hasn't expired
- Ensure no extra whitespace was added
- Create a new client secret if necessary
**Error:** `AADSTS700016: Application not found`
- Verify the Client ID is correct
- Ensure the app registration exists in the correct tenant
- Check the Tenant ID matches your organization
**Error:** `AADSTS90002: Tenant not found`
- Verify the Tenant ID is correct
- Ensure you're using the correct Azure environment (public vs. government)
**Error:** `Authorization failed` or `Forbidden`
- Verify the DNS Zone Contributor role is assigned
- Check the role is assigned at the DNS zone level
- Wait a few minutes for role assignment propagation
- Verify the resource group name is correct
**Error:** `Resource group not found`
- Check the resource group name spelling (case-sensitive)
- Ensure the resource group exists in the specified subscription
- Verify the subscription ID is correct
**Error:** `DNS zone not found`
- Verify the DNS zone exists in the resource group
- Check the domain matches the DNS zone name
- Ensure the app has access to the subscription
### Certificate Issuance Fails
**Error:** `DNS propagation timeout`
- Azure DNS typically propagates in 30-60 seconds
- Increase Propagation Timeout to 180 seconds
- Verify nameservers are correctly configured with your registrar
- Check Azure Status page for service issues
**Error:** `Record creation failed`
- Verify app registration has DNS Zone Contributor role
- Check for existing `_acme-challenge` TXT records that may conflict
- Review Charon logs for detailed API errors
**Error:** `Rate limit exceeded`
- Azure DNS has API rate limits per subscription
- Increase Polling Interval to reduce API calls
- Contact Azure support to increase limits if needed
### Nameserver Propagation
**Issue:** DNS changes not visible globally
- Nameserver changes can take 24-48 hours to propagate
- Use [DNS Checker](https://dnschecker.org/) to verify global propagation
- Verify your registrar shows Azure DNS nameservers
- Wait for full propagation before attempting certificate issuance
### Client Secret Expiration
**Issue:** Certificates stop renewing
- Client secrets have expiration dates
- Set calendar reminders before expiration
- Create new secret and update Charon configuration before expiry
- Consider using Managed Identities for Azure-hosted Charon deployments
## Security Recommendations
1. **Dedicated App Registration:** Create a separate app registration for Charon
2. **Least Privilege:** Use DNS Zone Contributor role (not broader roles)
3. **Secret Rotation:** Rotate client secrets before expiration (every 6-12 months)
4. **Conditional Access:** Consider conditional access policies for the app
5. **Audit Logging:** Enable Azure Activity Log for DNS operations
6. **Private Endpoints:** Use private endpoints if Charon runs in Azure
7. **Managed Identity:** Use Managed Identity if Charon is hosted in Azure (eliminates secrets)
8. **Monitor Sign-ins:** Review app sign-in logs in Microsoft Entra ID
## Client Secret Rotation
To rotate the client secret:
1. Navigate to your app registration → **Certificates & secrets**
2. Create a new client secret
3. Update the configuration in Charon with the new secret
4. Test the connection to verify the new secret works
5. Delete the old secret from the Azure portal
> **Best Practice:** Create the new secret before the old one expires to avoid downtime.
## Using Azure CLI for Verification (Optional)
Test configuration before adding to Charon:
```bash
# Login with service principal
az login --service-principal \
--username CLIENT_ID \
--password CLIENT_SECRET \
--tenant TENANT_ID
# Set subscription
az account set --subscription SUBSCRIPTION_ID
# List DNS zones
az network dns zone list \
--resource-group RESOURCE_GROUP_NAME
# Test record creation
az network dns record-set txt add-record \
--resource-group RESOURCE_GROUP_NAME \
--zone-name example.com \
--record-set-name _acme-challenge-test \
--value "test-value"
# Clean up test record
az network dns record-set txt remove-record \
--resource-group RESOURCE_GROUP_NAME \
--zone-name example.com \
--record-set-name _acme-challenge-test \
--value "test-value"
```
## Using Managed Identity (Azure-Hosted Charon)
If Charon runs in Azure (VM, Container Instance, AKS), consider using Managed Identity:
1. Enable System-assigned managed identity on your Azure resource
2. Assign **DNS Zone Contributor** role to the managed identity
3. Configure Charon to use managed identity authentication (no secrets needed)
> **Benefits:** No client secrets to manage, automatic credential rotation, enhanced security.
## Azure DNS Limitations
- **Zone-scoped permissions only:** Cannot restrict to specific record types within a zone
- **No private DNS support:** Charon requires public DNS for ACME challenges
- **Regional availability:** Azure DNS is a global service, no regional selection needed
- **Billing:** Azure DNS charges per zone and per million queries
## Cost Considerations
Azure DNS pricing (approximate):
- **Hosted zones:** ~$0.50/month per zone
- **DNS queries:** ~$0.40 per million queries
Certificate challenges generate minimal queries (<100 per certificate issuance).
## Additional Resources
- [Azure DNS Documentation](https://learn.microsoft.com/en-us/azure/dns/)
- [Microsoft Entra ID App Registration](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app)
- [Azure RBAC for DNS](https://learn.microsoft.com/en-us/azure/dns/dns-protect-zones-recordsets)
- [Caddy Azure DNS Module](https://caddyserver.com/docs/modules/dns.providers.azure)
- [Azure Status Page](https://status.azure.com/)
- [Azure CLI DNS Commands](https://learn.microsoft.com/en-us/cli/azure/network/dns)
## Related Documentation
- [DNS Providers Overview](../dns-providers.md)
- [Wildcard Certificates Guide](../certificates.md#wildcard-certificates)
- [DNS Challenges Troubleshooting](../../troubleshooting/dns-challenges.md)
````

View File

@@ -0,0 +1,327 @@
````markdown
# 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)
````

View File

@@ -1,37 +1,142 @@
# SSRF Remediation Plan (Index)
# Charon Feature & Remediation Tracker
This file is intentionally SSRF-focused only.
**Last Updated:** January 3, 2026
This document serves as the central index for all active plans, implementation specs, and outstanding work items.
---
## 1. SSRF Remediation
**Status:** 🔴 IN PROGRESS
The authoritative, Supervisor-updated SSRF plan is:
- [docs/plans/ssrf-remediation.md](docs/plans/ssrf-remediation.md)
- [docs/plans/ssrf-remediation.md](ssrf-remediation.md)
## Merge policy (Supervisor requirement)
### Merge Policy (Supervisor requirement)
- The global CodeQL exclusion for `go/request-forgery` in
[.github/codeql/codeql-config.yml](.github/codeql/codeql-config.yml) must be removed
[.github/codeql/codeql-config.yml](../../.github/codeql/codeql-config.yml) must be removed
in the same PR/merge as the underlying SSRF fixes.
- Phase 0 can include local-only recon (e.g., temporary local edit of CodeQL config to
surface findings), but must not be a mergeable intermediate state.
## SSRF call sites (current known)
### SSRF Call Sites (Current Known)
- Uptime monitor HTTP checks: `(*UptimeService).checkMonitor` in
[backend/internal/services/uptime_service.go](backend/internal/services/uptime_service.go)
- CrowdSec LAPI: `(*CrowdsecHandler).GetLAPIDecisions` and
`(*CrowdsecHandler).CheckLAPIHealth` in
[backend/internal/api/handlers/crowdsec_handler.go](backend/internal/api/handlers/crowdsec_handler.go)
- Caddy Admin API: `caddy.NewClient` and `(*Client).Load/GetConfig/Ping` in
[backend/internal/caddy/client.go](backend/internal/caddy/client.go)
- URL connectivity test (SSRF-sensitive client): `utils.TestURLConnectivity` in
[backend/internal/utils/url_testing.go](backend/internal/utils/url_testing.go)
| Location | Function | File |
|----------|----------|------|
| Uptime Monitor | `(*UptimeService).checkMonitor` | [uptime_service.go](../../backend/internal/services/uptime_service.go) |
| CrowdSec LAPI | `GetLAPIDecisions`, `CheckLAPIHealth` | [crowdsec_handler.go](../../backend/internal/api/handlers/crowdsec_handler.go) |
| Caddy Admin API | `NewClient`, `Load/GetConfig/Ping` | [client.go](../../backend/internal/caddy/client.go) |
| URL Connectivity Test | `utils.TestURLConnectivity` | [url_testing.go](../../backend/internal/utils/url_testing.go) |
## Relocated content (no deletions)
---
- Patch coverage (Codecov) plan (previous Appendix A):
[docs/plans/patch-coverage-codecov.md](docs/plans/patch-coverage-codecov.md)
- CodeQL/Trivy local scan hygiene notes (generated artifacts, skip dirs, etc.):
[docs/plans/codeql-local-hygiene.md](docs/plans/codeql-local-hygiene.md)
- DNS provider feature spec (implementation-level):
[docs/implementation/dns_providers_IMPLEMENTATION.md](docs/implementation/dns_providers_IMPLEMENTATION.md)
## 2. DNS Provider Feature (Issue #21)
### Core Implementation
**Status:** ✅ COMPLETE
- **Implementation Spec:** [dns_providers_IMPLEMENTATION.md](../implementation/dns_providers_IMPLEMENTATION.md)
- **Pull Request:** [#461](https://github.com/Wikid82/Charon/pull/461)
All core components implemented:
| Layer | Component | Status |
|-------|-----------|--------|
| Backend | Encryption Service (`crypto/encryption.go`) | ✅ Complete |
| Backend | DNSProvider Model | ✅ Complete |
| Backend | DNS Provider Service | ✅ Complete |
| Backend | DNS Provider Handler | ✅ Complete |
| Backend | Routes Registered | ✅ Complete |
| Backend | Caddy DNS-01 Integration | ✅ Complete |
| Frontend | API Client & Hooks | ✅ Complete |
| Frontend | DNS Providers Page & Form | ✅ Complete |
| Frontend | ProxyHost Integration | ✅ Complete |
| Frontend | Translations | ✅ Complete |
### Acceptance Criteria Verification
| Criterion | Status |
|-----------|--------|
| Users can add, edit, delete, and test DNS provider configurations | ✅ Implemented |
| Credentials encrypted at rest using AES-256-GCM | ✅ Implemented |
| Credentials never exposed in API responses | ✅ Implemented (`json:"-"`) |
| Proxy hosts with wildcard domains can select a DNS provider | ✅ Implemented |
| Caddy successfully obtains wildcard certificates via DNS-01 | ✅ Implemented |
| Backend unit test coverage ≥ 85% | ✅ **85.2%** (verified 2026-01-03) |
| Frontend unit test coverage ≥ 85% | ✅ **87.8%** (verified 2026-01-03) |
| User documentation completed | ✅ Complete (5 provider guides) |
| All translations added | ✅ Complete |
### Verification Results (2026-01-03)
| Check | Result |
|-------|--------|
| Backend Coverage | ✅ 85.2% (threshold: 85%) |
| Frontend Coverage | ✅ 87.8% (threshold: 85%) |
| Security Scan (Trivy) | ✅ 0 Critical, 0 High |
| Security Scan (govulncheck) | ✅ 0 vulnerabilities |
| Pre-commit Hooks | ✅ All 11 hooks passed |
| CHANGELOG | ✅ Entry exists in [Unreleased] |
### Outstanding Items (Pre-Merge)
- [x] ~~Run backend coverage report~~**85.2%**
- [x] ~~Run frontend coverage report~~**87.8%**
- [x] ~~Complete Google Cloud DNS setup guide~~ — Created ✅
- [x] ~~Complete Azure DNS setup guide~~ — Created ✅
- [ ] Manual E2E validation: DNS provider → wildcard proxy → certificate issued
- [x] ~~CHANGELOG entry for DNS provider feature~~ — Already present ✅
- [x] ~~Security scans (Trivy, govulncheck)~~ — Passed ✅
### Future Enhancements
**Status:** 📋 PLANNING
- **Planning Doc:** [dns_challenge_future_features.md](dns_challenge_future_features.md)
| Priority | Feature | Est. Time | Status |
|----------|---------|-----------|--------|
| **P0** | Audit Logging for Credential Operations | 8-12 hrs | ❌ Not Started |
| **P1** | Key Rotation Automation | 16-20 hrs | ❌ Not Started |
| **P1** | Multi-Credential per Provider (Zone-Specific) | 12-16 hrs | ❌ Not Started |
| **P2** | DNS Provider Auto-Detection | 6-8 hrs | ❌ Not Started |
| **P3** | Custom DNS Provider Plugins | 20-24 hrs | ❌ Not Started |
**Recommended Implementation Order:**
1. Audit Logging (Security/Compliance baseline for SOC 2, GDPR, HIPAA)
2. Key Rotation (Security hardening, annual rotation support)
3. Multi-Credential (Enterprise/MSP multi-tenancy)
4. Auto-Detection (UX improvement)
5. Custom Plugins (Extensibility for power users)
---
## 3. Related Documents (Index)
| Document | Description |
|----------|-------------|
| [patch-coverage-codecov.md](patch-coverage-codecov.md) | Codecov patch coverage plan |
| [codeql-local-hygiene.md](codeql-local-hygiene.md) | CodeQL/Trivy local scan hygiene notes |
| [dns_providers_IMPLEMENTATION.md](../implementation/dns_providers_IMPLEMENTATION.md) | DNS provider full implementation spec |
| [dns_challenge_future_features.md](dns_challenge_future_features.md) | DNS challenge future enhancements plan |
---
## 4. Definition of Done (All Features)
Before any feature is considered complete:
- [ ] Backend unit test coverage ≥ 85%
- [ ] Frontend unit test coverage ≥ 85%
- [ ] TypeScript check passes (`npm run type-check`)
- [ ] Pre-commit hooks pass (`pre-commit run --all-files`)
- [ ] CodeQL scans: zero Critical/High issues
- [ ] Trivy scans: zero Critical/High vulnerabilities
- [ ] All linters pass
- [ ] Documentation updated
- [ ] CHANGELOG updated