feat: add nightly branch workflow
This commit is contained in:
@@ -150,6 +150,7 @@ The details modal displays:
|
||||
The details field contains a JSON object with event-specific information:
|
||||
|
||||
**Create Event Example:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Cloudflare Production",
|
||||
@@ -159,6 +160,7 @@ The details field contains a JSON object with event-specific information:
|
||||
```
|
||||
|
||||
**Update Event Example:**
|
||||
|
||||
```json
|
||||
{
|
||||
"changed_fields": ["credentials", "is_default"],
|
||||
@@ -172,6 +174,7 @@ The details field contains a JSON object with event-specific information:
|
||||
```
|
||||
|
||||
**Test Event Example:**
|
||||
|
||||
```json
|
||||
{
|
||||
"test_result": "success",
|
||||
@@ -180,6 +183,7 @@ The details field contains a JSON object with event-specific information:
|
||||
```
|
||||
|
||||
**Decrypt Event Example:**
|
||||
|
||||
```json
|
||||
{
|
||||
"purpose": "certificate_issuance",
|
||||
@@ -230,12 +234,14 @@ Export audit logs for external analysis, compliance reporting, or archival:
|
||||
### Scenario 1: New DNS Provider Setup
|
||||
|
||||
**Timeline:**
|
||||
|
||||
1. User `admin@example.com` logs in from `192.168.1.100`
|
||||
2. Navigates to DNS Providers page
|
||||
3. Clicks "Add DNS Provider"
|
||||
4. Fills in Cloudflare credentials and clicks Save
|
||||
|
||||
**Audit Log Entries:**
|
||||
|
||||
```
|
||||
2026-01-03 14:23:45 | user:5 | dns_provider_create | dns_provider | {"name":"Cloudflare Prod","type":"cloudflare","is_default":true}
|
||||
```
|
||||
@@ -243,10 +249,12 @@ Export audit logs for external analysis, compliance reporting, or archival:
|
||||
### Scenario 2: Credential Testing
|
||||
|
||||
**Timeline:**
|
||||
|
||||
1. User tests existing provider credentials
|
||||
2. API validation succeeds
|
||||
|
||||
**Audit Log Entries:**
|
||||
|
||||
```
|
||||
2026-01-03 14:25:12 | user:5 | credential_test | dns_provider | {"test_result":"success","response_time_ms":342}
|
||||
```
|
||||
@@ -254,12 +262,14 @@ Export audit logs for external analysis, compliance reporting, or archival:
|
||||
### Scenario 3: Certificate Issuance
|
||||
|
||||
**Timeline:**
|
||||
|
||||
1. Caddy detects new host requires SSL certificate
|
||||
2. Caddy decrypts DNS provider credentials
|
||||
3. ACME DNS-01 challenge completes successfully
|
||||
4. Certificate issued
|
||||
|
||||
**Audit Log Entries:**
|
||||
|
||||
```
|
||||
2026-01-03 14:30:00 | system | credential_decrypt | dns_provider | {"purpose":"certificate_issuance","success":true}
|
||||
2026-01-03 14:30:45 | system | certificate_issued | certificate | {"domain":"app.example.com","provider":"cloudflare","result":"success"}
|
||||
@@ -268,10 +278,12 @@ Export audit logs for external analysis, compliance reporting, or archival:
|
||||
### Scenario 4: Provider Update
|
||||
|
||||
**Timeline:**
|
||||
|
||||
1. User updates default provider setting
|
||||
2. API saves changes
|
||||
|
||||
**Audit Log Entries:**
|
||||
|
||||
```
|
||||
2026-01-03 15:00:22 | user:5 | dns_provider_update | dns_provider | {"changed_fields":["is_default"],"old_values":{"is_default":false},"new_values":{"is_default":true}}
|
||||
```
|
||||
@@ -279,10 +291,12 @@ Export audit logs for external analysis, compliance reporting, or archival:
|
||||
### Scenario 5: Provider Deletion
|
||||
|
||||
**Timeline:**
|
||||
|
||||
1. User deletes unused DNS provider
|
||||
2. Credentials are securely wiped
|
||||
|
||||
**Audit Log Entries:**
|
||||
|
||||
```
|
||||
2026-01-03 16:45:33 | user:5 | dns_provider_delete | dns_provider | {"name":"Old Provider","type":"route53","had_credentials":true}
|
||||
```
|
||||
@@ -342,6 +356,7 @@ Audit logging is designed for minimal performance impact:
|
||||
- **Automatic Cleanup**: Old logs are periodically deleted to prevent database bloat
|
||||
|
||||
**Typical Impact:**
|
||||
|
||||
- API request latency: +0.1ms (sending to channel)
|
||||
- Database writes: Batched in background, no user-facing impact
|
||||
- Storage: ~500 bytes per event, ~1.5 GB per year at 100 events/day
|
||||
@@ -371,11 +386,13 @@ If audit log pages load slowly:
|
||||
Retrieve audit logs with pagination and filtering.
|
||||
|
||||
**Endpoint:**
|
||||
|
||||
```http
|
||||
GET /api/v1/audit-logs
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
- `page` (int, default: 1): Page number
|
||||
- `limit` (int, default: 50, max: 100): Results per page
|
||||
- `actor` (string): Filter by actor (user ID or "system")
|
||||
@@ -386,12 +403,14 @@ GET /api/v1/audit-logs
|
||||
- `end_date` (RFC3339): End of date range
|
||||
|
||||
**Example Request:**
|
||||
|
||||
```bash
|
||||
curl -X GET "https://charon.example.com/api/v1/audit-logs?page=1&limit=50&event_category=dns_provider&start_date=2026-01-01T00:00:00Z" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"audit_logs": [
|
||||
@@ -423,20 +442,24 @@ curl -X GET "https://charon.example.com/api/v1/audit-logs?page=1&limit=50&event_
|
||||
Retrieve complete details for a specific audit event.
|
||||
|
||||
**Endpoint:**
|
||||
|
||||
```http
|
||||
GET /api/v1/audit-logs/:uuid
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `uuid` (string, required): Event UUID
|
||||
|
||||
**Example Request:**
|
||||
|
||||
```bash
|
||||
curl -X GET "https://charon.example.com/api/v1/audit-logs/550e8400-e29b-41d4-a716-446655440000" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
@@ -458,24 +481,29 @@ curl -X GET "https://charon.example.com/api/v1/audit-logs/550e8400-e29b-41d4-a71
|
||||
Retrieve all audit events for a specific DNS provider.
|
||||
|
||||
**Endpoint:**
|
||||
|
||||
```http
|
||||
GET /api/v1/dns-providers/:id/audit-logs
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `id` (int, required): DNS provider ID
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
- `page` (int, default: 1): Page number
|
||||
- `limit` (int, default: 50, max: 100): Results per page
|
||||
|
||||
**Example Request:**
|
||||
|
||||
```bash
|
||||
curl -X GET "https://charon.example.com/api/v1/dns-providers/3/audit-logs?page=1&limit=50" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"audit_logs": [
|
||||
@@ -543,11 +571,13 @@ Authorization: Bearer YOUR_API_TOKEN
|
||||
Configure how long audit logs are retained before automatic deletion:
|
||||
|
||||
**Environment Variable:**
|
||||
|
||||
```bash
|
||||
AUDIT_LOG_RETENTION_DAYS=90 # Default: 90 days
|
||||
```
|
||||
|
||||
**Docker Compose:**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
charon:
|
||||
@@ -560,6 +590,7 @@ services:
|
||||
Configure the size of the audit log channel buffer (advanced):
|
||||
|
||||
**Environment Variable:**
|
||||
|
||||
```bash
|
||||
AUDIT_LOG_CHANNEL_SIZE=1000 # Default: 1000 events
|
||||
```
|
||||
|
||||
@@ -354,9 +354,9 @@ sudo chmod -R o-w /etc/charon/plugins
|
||||
|
||||
### Getting Help
|
||||
|
||||
- **GitHub Discussions:** https://github.com/Wikid82/charon/discussions
|
||||
- **Issue Tracker:** https://github.com/Wikid82/charon/issues
|
||||
- **Documentation:** https://docs.charon.example.com
|
||||
- **GitHub Discussions:** <https://github.com/Wikid82/charon/discussions>
|
||||
- **Issue Tracker:** <https://github.com/Wikid82/charon/issues>
|
||||
- **Documentation:** <https://docs.charon.example.com>
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ DNS Provider Auto-Detection is an intelligent feature that automatically identif
|
||||
### When Detection Occurs
|
||||
|
||||
Auto-detection runs automatically when you:
|
||||
|
||||
- Enter a wildcard domain (`*.example.com`) in the proxy host creation form
|
||||
- The domain requires DNS-01 challenge validation for Let's Encrypt SSL certificates
|
||||
|
||||
@@ -55,6 +56,7 @@ When creating a new proxy host with a wildcard domain:
|
||||
4. If a match is found, the provider is automatically selected
|
||||
|
||||
**Visual Indicator**: A detection status badge appears next to the DNS Provider dropdown showing:
|
||||
|
||||
- ✓ Provider detected
|
||||
- ⚠ No provider detected
|
||||
- ℹ Multiple nameservers found
|
||||
@@ -166,6 +168,7 @@ The system recognizes the following DNS providers by their nameserver patterns:
|
||||
### Provider-Specific Examples
|
||||
|
||||
#### Cloudflare
|
||||
|
||||
```
|
||||
Nameservers:
|
||||
ns1.cloudflare.com
|
||||
@@ -175,6 +178,7 @@ Detected: cloudflare (High confidence)
|
||||
```
|
||||
|
||||
#### AWS Route 53
|
||||
|
||||
```
|
||||
Nameservers:
|
||||
ns-1234.awsdns-12.com
|
||||
@@ -184,6 +188,7 @@ Detected: route53 (High confidence)
|
||||
```
|
||||
|
||||
#### Google Cloud DNS
|
||||
|
||||
```
|
||||
Nameservers:
|
||||
ns-cloud-a1.googledomains.com
|
||||
@@ -193,6 +198,7 @@ Detected: googleclouddns (High confidence)
|
||||
```
|
||||
|
||||
#### DigitalOcean
|
||||
|
||||
```
|
||||
Nameservers:
|
||||
ns1.digitalocean.com
|
||||
@@ -240,6 +246,7 @@ For custom or internal nameservers:
|
||||
4. Configure appropriate API credentials in the DNS Provider settings
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Domain: *.corp.internal
|
||||
Nameservers: ns1.corp.internal, ns2.corp.internal
|
||||
@@ -255,11 +262,13 @@ Manual selection required: Select compatible provider or configure custom
|
||||
**Symptom**: Error message "Failed to detect DNS provider" or "Domain not found"
|
||||
|
||||
**Causes**:
|
||||
|
||||
- Domain doesn't exist yet
|
||||
- Domain not propagated to public DNS
|
||||
- DNS resolution blocked by firewall
|
||||
|
||||
**Solutions**:
|
||||
|
||||
- Verify domain exists and is registered
|
||||
- Wait for DNS propagation (up to 48 hours)
|
||||
- Check network connectivity and DNS resolution
|
||||
@@ -270,11 +279,13 @@ Manual selection required: Select compatible provider or configure custom
|
||||
**Symptom**: System detects incorrect provider type
|
||||
|
||||
**Causes**:
|
||||
|
||||
- Domain using DNS proxy/forwarding service
|
||||
- Recent nameserver change not yet propagated
|
||||
- Multiple providers in nameserver list
|
||||
|
||||
**Solutions**:
|
||||
|
||||
- Wait for DNS propagation (up to 24 hours)
|
||||
- Manually override provider selection
|
||||
- Verify nameservers at your domain registrar
|
||||
@@ -285,11 +296,13 @@ Manual selection required: Select compatible provider or configure custom
|
||||
**Symptom**: Detection shows multiple provider types
|
||||
|
||||
**Causes**:
|
||||
|
||||
- Nameservers from different providers (unusual)
|
||||
- DNS migration in progress
|
||||
- Misconfigured nameservers
|
||||
|
||||
**Solutions**:
|
||||
|
||||
- Check nameserver configuration at your registrar
|
||||
- Complete DNS migration to single provider
|
||||
- Manually select the primary/correct provider
|
||||
@@ -300,12 +313,14 @@ Manual selection required: Select compatible provider or configure custom
|
||||
**Symptom**: Provider detected but no matching provider configured in system
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
Detected Provider Type: cloudflare
|
||||
Error: No DNS provider of type 'cloudflare' is configured
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Navigate to **Settings** → **DNS Providers**
|
||||
2. Click **Add DNS Provider**
|
||||
3. Select the detected provider type (e.g., Cloudflare)
|
||||
@@ -326,6 +341,7 @@ Error: No DNS provider of type 'cloudflare' is configured
|
||||
**This is expected behavior**. Custom DNS servers don't match public provider patterns.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Manually select a provider that uses a compatible API
|
||||
2. If using BIND, PowerDNS, or other custom DNS:
|
||||
- Configure acme.sh or certbot direct integration
|
||||
@@ -342,6 +358,7 @@ Error: No DNS provider of type 'cloudflare' is configured
|
||||
**Cause**: Results cached for 1 hour
|
||||
|
||||
**Solutions**:
|
||||
|
||||
- Wait up to 1 hour for cache to expire
|
||||
- Use **Detect Provider** button for manual detection (bypasses cache)
|
||||
- DNS propagation may also take additional time (separate from caching)
|
||||
@@ -375,6 +392,7 @@ Authorization: Bearer YOUR_API_TOKEN
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `domain` (required): Full domain name including wildcard (e.g., `*.example.com`)
|
||||
|
||||
#### Response: Success
|
||||
@@ -395,6 +413,7 @@ Authorization: Bearer YOUR_API_TOKEN
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
|
||||
- `status`: `"detected"` or `"not_detected"`
|
||||
- `provider_type`: Detected provider type (string) or `null`
|
||||
- `confidence`: `"high"`, `"medium"`, `"low"`, or `"none"`
|
||||
@@ -430,6 +449,7 @@ Authorization: Bearer YOUR_API_TOKEN
|
||||
```
|
||||
|
||||
**HTTP Status Codes**:
|
||||
|
||||
- `200 OK`: Detection completed successfully
|
||||
- `400 Bad Request`: Invalid domain format
|
||||
- `401 Unauthorized`: Missing or invalid API token
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
DNS Provider Auto-Detection is an intelligent system that automatically identifies which DNS provider manages your domain's nameservers. When configuring wildcard SSL certificates in Charon, you no longer need to manually select your DNS provider—Charon detects it for you in less than a second.
|
||||
|
||||
**Who Benefits:**
|
||||
|
||||
- **Managed Service Providers (MSPs):** Managing multiple customer domains across different DNS providers
|
||||
- **System Administrators:** Setting up wildcard certificates for multiple domains
|
||||
- **DevOps Teams:** Automating certificate provisioning workflows
|
||||
- **Small Businesses:** Simplifying SSL certificate setup without technical expertise
|
||||
|
||||
**Key Benefits:**
|
||||
|
||||
- ⚡ **Instant Detection:** Identifies your DNS provider in 100-200ms
|
||||
- 🎯 **High Accuracy:** Supports 10+ major DNS providers with confidence scoring
|
||||
- ⏱️ **Time Savings:** Reduces setup time from 5-10 minutes to under 30 seconds
|
||||
@@ -37,6 +39,7 @@ DNS auto-detection uses a simple but powerful process:
|
||||
6. **Manual Override:** You can always override the auto-detected provider
|
||||
|
||||
**Technical Details:**
|
||||
|
||||
- Uses standard DNS NS (nameserver) record lookups
|
||||
- Matches nameserver hostnames against built-in pattern database
|
||||
- Case-insensitive pattern matching for reliability
|
||||
@@ -108,6 +111,7 @@ Charon has built-in detection for these major DNS providers:
|
||||
4. **Review Detection Result**
|
||||
|
||||
**High Confidence Example:**
|
||||
|
||||
```
|
||||
✓ Cloudflare detected (High confidence)
|
||||
|
||||
@@ -119,6 +123,7 @@ Charon has built-in detection for these major DNS providers:
|
||||
```
|
||||
|
||||
**Medium/Low Confidence Example:**
|
||||
|
||||
```
|
||||
⚠ DigitalOcean detected (Medium confidence)
|
||||
|
||||
@@ -132,6 +137,7 @@ Charon has built-in detection for these major DNS providers:
|
||||
```
|
||||
|
||||
**No Detection Example:**
|
||||
|
||||
```
|
||||
✗ DNS provider not detected
|
||||
|
||||
@@ -154,6 +160,7 @@ Charon has built-in detection for these major DNS providers:
|
||||
- Click **Save**
|
||||
|
||||
**Tips:**
|
||||
|
||||
- Detection works best with production domains already using their final nameservers
|
||||
- If detection fails, check that your domain's DNS is properly configured
|
||||
- Manual selection is always available as a fallback
|
||||
@@ -223,9 +230,11 @@ curl -X POST https://your-charon-instance/api/v1/dns-providers/detect \
|
||||
```
|
||||
|
||||
**Request Parameters:**
|
||||
|
||||
- `domain` (string, required): Domain to detect (with or without wildcard `*`)
|
||||
|
||||
**Response Fields:**
|
||||
|
||||
- `domain` (string): The base domain that was checked
|
||||
- `detected` (boolean): Whether a provider was successfully identified
|
||||
- `provider_type` (string): Type identifier for the detected provider
|
||||
@@ -267,6 +276,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
```
|
||||
|
||||
**Response Format:**
|
||||
|
||||
- `patterns` (object): Map of nameserver patterns to provider type identifiers
|
||||
- Pattern keys are substring matches (case-insensitive)
|
||||
- Provider type values match Charon's DNS provider types
|
||||
@@ -280,6 +290,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
**Scenario:** MSP managing 50+ customer domains across multiple DNS providers
|
||||
|
||||
**Before Auto-Detection:**
|
||||
|
||||
- Manually research DNS provider for each customer domain
|
||||
- Look up nameservers using external tools (`dig`, `nslookup`)
|
||||
- Risk of selecting wrong provider → certificate issuance fails
|
||||
@@ -287,6 +298,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
- Total time for 50 domains: 4-8 hours
|
||||
|
||||
**With Auto-Detection:**
|
||||
|
||||
- Enter customer's wildcard domain
|
||||
- Provider detected automatically in <200ms
|
||||
- One-click to use detected provider
|
||||
@@ -302,6 +314,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
**Scenario:** Service provider managing customers using different DNS providers
|
||||
|
||||
**Customer Portfolio:**
|
||||
|
||||
- `*.customer1.com` → Cloudflare (High confidence)
|
||||
- `*.customer2.com` → Route53 (High confidence)
|
||||
- `*.customer3.com` → DigitalOcean (High confidence)
|
||||
@@ -309,6 +322,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
- `*.customer5.com` → Namecheap (Medium confidence - verify)
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- No need to remember which customer uses which provider
|
||||
- Automatic correct provider suggestion
|
||||
- Confidence levels flag domains needing verification
|
||||
@@ -321,6 +335,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
**Scenario:** Company with domains split across multiple DNS providers
|
||||
|
||||
**Infrastructure:**
|
||||
|
||||
- Production domains (`*.prod.company.com`) → Cloudflare
|
||||
- Development domains (`*.dev.company.com`) → DigitalOcean
|
||||
- Legacy domains (`*.legacy.company.com`) → Namecheap
|
||||
@@ -329,6 +344,7 @@ curl https://your-charon-instance/api/v1/dns-providers/detection-patterns \
|
||||
**Challenge:** Developers frequently set up new wildcard proxies and forget which DNS provider manages each environment.
|
||||
|
||||
**Solution:** Auto-detection eliminates guesswork:
|
||||
|
||||
- Developers enter domain
|
||||
- Correct provider automatically detected
|
||||
- Zero configuration errors
|
||||
@@ -369,6 +385,7 @@ fi
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Fully automated provisioning
|
||||
- Self-documenting configuration
|
||||
- Confidence checks prevent misconfiguration
|
||||
@@ -407,6 +424,7 @@ fi
|
||||
**Solutions:**
|
||||
|
||||
**Check Domain's Nameservers:**
|
||||
|
||||
```bash
|
||||
# Linux/Mac
|
||||
dig NS example.com +short
|
||||
@@ -416,12 +434,14 @@ nslookup -type=NS example.com
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
ns1.cloudflare.com.
|
||||
ns2.cloudflare.com.
|
||||
```
|
||||
|
||||
**Verify Nameserver Propagation:**
|
||||
|
||||
```bash
|
||||
# Check multiple DNS servers
|
||||
dig @8.8.8.8 NS example.com +short
|
||||
@@ -429,16 +449,19 @@ dig @1.1.1.1 NS example.com +short
|
||||
```
|
||||
|
||||
**Wait for DNS Propagation:**
|
||||
|
||||
- Initial DNS setup: Up to 48 hours
|
||||
- DNS changes: Up to 24 hours
|
||||
- Check again after propagation completes
|
||||
|
||||
**Use Manual Provider Selection:**
|
||||
|
||||
- Click **Select Manually** button
|
||||
- Choose provider from dropdown
|
||||
- Detection is optional—manual selection always works
|
||||
|
||||
**Check Network Connectivity:**
|
||||
|
||||
```bash
|
||||
# Test DNS connectivity
|
||||
dig cloudflare.com +short
|
||||
@@ -470,6 +493,7 @@ dig cloudflare.com +short
|
||||
**Solutions:**
|
||||
|
||||
**Verify Current Nameservers:**
|
||||
|
||||
```bash
|
||||
dig NS example.com +short
|
||||
```
|
||||
@@ -477,16 +501,19 @@ dig NS example.com +short
|
||||
Compare with detected nameservers in Charon's result.
|
||||
|
||||
**Clear Charon's Detection Cache:**
|
||||
|
||||
- Cache expires automatically after 1 hour
|
||||
- Wait 60 minutes and try detection again
|
||||
- Or restart Charon to clear in-memory cache
|
||||
|
||||
**Check DNS Provider Account:**
|
||||
|
||||
- Log into your DNS provider's control panel
|
||||
- Verify the nameservers listed there
|
||||
- Compare with Charon's detection result
|
||||
|
||||
**Use Manual Override:**
|
||||
|
||||
- If detection is consistently wrong
|
||||
- Click **Select Manually**
|
||||
- Choose correct provider
|
||||
@@ -499,6 +526,7 @@ Compare with detected nameservers in Charon's result.
|
||||
**Symptom:** "DigitalOcean detected (Medium confidence)" or "Low confidence"
|
||||
|
||||
**What This Means:**
|
||||
|
||||
- Nameserver pattern match is partial or ambiguous
|
||||
- Provider type identified, but match isn't strong
|
||||
- Manual verification recommended before proceeding
|
||||
@@ -555,16 +583,19 @@ the typical pattern. Please verify this is correct.
|
||||
**Symptom:** Detection hangs or takes more than 5 seconds
|
||||
|
||||
**Possible Causes:**
|
||||
|
||||
- DNS server not responding
|
||||
- Network latency or packet loss
|
||||
- Domain's authoritative DNS servers offline
|
||||
|
||||
**Built-in Protections:**
|
||||
|
||||
- Detection timeout: 10 seconds maximum
|
||||
- After timeout, detection fails gracefully
|
||||
- Error message: "DNS lookup timeout"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
- Wait for timeout (max 10 seconds)
|
||||
- Check network connectivity
|
||||
- Verify domain's DNS is operational
|
||||
@@ -577,6 +608,7 @@ the typical pattern. Please verify this is correct.
|
||||
**Symptom:** Detection shows old provider after DNS migration
|
||||
|
||||
**Explanation:**
|
||||
|
||||
- Successful detections cached for 1 hour
|
||||
- Improves performance for repeated requests
|
||||
- May show outdated results during cache window
|
||||
@@ -584,15 +616,18 @@ the typical pattern. Please verify this is correct.
|
||||
**Solutions:**
|
||||
|
||||
**Wait for Cache Expiration:**
|
||||
|
||||
- Cache automatically expires after 1 hour
|
||||
- Try detection again after 60 minutes
|
||||
|
||||
**Restart Charon:**
|
||||
|
||||
- Cache is in-memory (not persistent)
|
||||
- Restarting clears all cached detections
|
||||
- Only necessary if you need immediate refresh
|
||||
|
||||
**Use Manual Selection:**
|
||||
|
||||
- Override cached detection
|
||||
- Select correct provider manually
|
||||
- Detection cache doesn't affect manual selection
|
||||
@@ -629,6 +664,7 @@ Content-Type: application/json
|
||||
| `domain` | string | Yes | Domain to detect (with or without `*.` wildcard) |
|
||||
|
||||
**Valid Domain Formats:**
|
||||
|
||||
- `example.com` → base domain
|
||||
- `*.example.com` → wildcard (auto-stripped to base domain)
|
||||
- `subdomain.example.com` → uses `example.com` for detection
|
||||
@@ -669,6 +705,7 @@ Content-Type: application/json
|
||||
| `error` | string | Error message (only present if detection failed) |
|
||||
|
||||
**Confidence Scoring:**
|
||||
|
||||
- **High (≥80%):** Most nameservers match pattern, strong confidence
|
||||
- **Medium (50-79%):** Some nameservers match, partial confidence
|
||||
- **Low (1-49%):** Few nameservers match, weak confidence
|
||||
@@ -677,6 +714,7 @@ Content-Type: application/json
|
||||
**Error Responses:**
|
||||
|
||||
**400 Bad Request** - Invalid domain
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "domain is required"
|
||||
@@ -684,6 +722,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Missing or invalid token
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Unauthorized"
|
||||
@@ -691,6 +730,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**500 Internal Server Error** - Detection failure
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "example.com",
|
||||
@@ -702,12 +742,14 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Status Codes:**
|
||||
|
||||
- `200 OK` - Detection completed (success or failure)
|
||||
- `400 Bad Request` - Invalid request parameters
|
||||
- `401 Unauthorized` - Authentication required or failed
|
||||
- `500 Internal Server Error` - Unexpected server error
|
||||
|
||||
**Rate Limiting:**
|
||||
|
||||
- Detection results cached for 1 hour
|
||||
- Repeated requests for same domain return cached result
|
||||
- No explicit rate limit (DNS timeout provides natural throttling)
|
||||
@@ -827,11 +869,13 @@ Authorization: Bearer YOUR_TOKEN
|
||||
```
|
||||
|
||||
**Response Format:**
|
||||
|
||||
- `patterns` (object): Map of nameserver patterns to provider types
|
||||
- **Keys:** Substring pattern to match in nameserver hostname (case-insensitive)
|
||||
- **Values:** Provider type identifier used in Charon
|
||||
|
||||
**Pattern Matching:**
|
||||
|
||||
- Case-insensitive substring matching
|
||||
- If any nameserver contains pattern, it's a match
|
||||
- Multiple patterns can match the same provider (e.g., Google Cloud DNS)
|
||||
@@ -840,6 +884,7 @@ Authorization: Bearer YOUR_TOKEN
|
||||
**Error Responses:**
|
||||
|
||||
**401 Unauthorized** - Missing or invalid token
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Unauthorized"
|
||||
@@ -847,6 +892,7 @@ Authorization: Bearer YOUR_TOKEN
|
||||
```
|
||||
|
||||
**Status Codes:**
|
||||
|
||||
- `200 OK` - Patterns returned successfully
|
||||
- `401 Unauthorized` - Authentication required or failed
|
||||
|
||||
@@ -859,6 +905,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
|
||||
- Building custom detection tools
|
||||
- Debugging detection issues
|
||||
- Understanding which providers are supported
|
||||
@@ -871,6 +918,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### Detection Speed
|
||||
|
||||
**Typical Performance:**
|
||||
|
||||
- **First Detection:** 100-200ms (includes DNS lookup)
|
||||
- **Cached Detection:** <1ms (from in-memory cache)
|
||||
- **DNS Timeout:** 10 seconds maximum (prevents hanging)
|
||||
@@ -886,6 +934,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
| Network latency | Varies | Between Charon and DNS servers |
|
||||
|
||||
**Performance Optimization:**
|
||||
|
||||
- Results cached for 1 hour
|
||||
- Reduces repeated DNS lookups
|
||||
- Cache hit rate typically 60-80%+ for active domains
|
||||
@@ -907,22 +956,26 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Cache Key:** Base domain (e.g., `example.com`)
|
||||
|
||||
**Cache Invalidation:**
|
||||
|
||||
- Automatic expiration after TTL
|
||||
- No manual invalidation API
|
||||
- Restart Charon to clear all cached entries
|
||||
|
||||
**Cache Hit Scenarios:**
|
||||
|
||||
- Same domain detected multiple times
|
||||
- Multiple wildcard proxies for same domain
|
||||
- Repeated API calls within 1-hour window
|
||||
|
||||
**Cache Miss Scenarios:**
|
||||
|
||||
- First detection for a domain
|
||||
- Cache entry expired (>1 hour old)
|
||||
- Domain's DNS recently changed
|
||||
- Charon restarted
|
||||
|
||||
**Performance Impact:**
|
||||
|
||||
- Cache hit: <1ms response time
|
||||
- Cache miss: 100-200ms response time (DNS lookup required)
|
||||
- Cache reduces DNS query load by ~80%
|
||||
@@ -941,6 +994,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
| DNS timeout | 10 seconds | Per-request maximum |
|
||||
|
||||
**Recommendations for High-Volume Usage:**
|
||||
|
||||
- Deploy Charon with adequate memory (cache can grow)
|
||||
- Consider DNS server location/latency
|
||||
- Monitor cache hit rate for optimization
|
||||
@@ -953,12 +1007,14 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### Authentication & Authorization
|
||||
|
||||
**Endpoint Security:**
|
||||
|
||||
- All detection endpoints require authentication
|
||||
- Bearer token must be provided in `Authorization` header
|
||||
- Same permission model as DNS provider management
|
||||
- Unauthorized requests return `401 Unauthorized`
|
||||
|
||||
**Permission Requirements:**
|
||||
|
||||
- User must have access to DNS provider features
|
||||
- No special permissions required for detection
|
||||
- Detection doesn't expose sensitive credentials
|
||||
@@ -969,11 +1025,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### Data Privacy
|
||||
|
||||
**What Charon Collects:**
|
||||
|
||||
- ✅ Domain name (from user input)
|
||||
- ✅ Nameserver hostnames (from DNS lookup)
|
||||
- ✅ Detection result (cached for 1 hour)
|
||||
|
||||
**What Charon Does NOT Collect:**
|
||||
|
||||
- ❌ DNS credentials or API keys
|
||||
- ❌ Certificate private keys
|
||||
- ❌ User browsing history
|
||||
@@ -981,12 +1039,14 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
- ❌ Personal identifiable information (beyond domain ownership)
|
||||
|
||||
**Data Storage:**
|
||||
|
||||
- Detection results cached in-memory only
|
||||
- No persistent storage of detection data
|
||||
- Cache cleared on restart
|
||||
- No logging of detected domains (unless debug logging enabled)
|
||||
|
||||
**Third-Party Access:**
|
||||
|
||||
- No data sent to third-party services
|
||||
- DNS lookups go directly to configured DNS resolvers
|
||||
- No analytics or telemetry for detection feature
|
||||
@@ -996,6 +1056,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### DNS Query Security
|
||||
|
||||
**Query Characteristics:**
|
||||
|
||||
- Standard DNS NS (nameserver) record lookups
|
||||
- Uses system DNS resolver by default
|
||||
- Respects DNS timeout (10 seconds)
|
||||
@@ -1003,12 +1064,14 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
- Read-only DNS operations
|
||||
|
||||
**Security Measures:**
|
||||
|
||||
- DNS timeout prevents hanging on unresponsive servers
|
||||
- No user-controlled DNS servers (uses system config)
|
||||
- Input validation on domain names
|
||||
- Error handling for malformed responses
|
||||
|
||||
**Network Security:**
|
||||
|
||||
- DNS queries over UDP/TCP port 53
|
||||
- No TLS/HTTPS for DNS (standard DNS protocol)
|
||||
- Consider using DNS-over-HTTPS (DoH) in system resolver for privacy
|
||||
@@ -1029,6 +1092,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
| Credential exposure | Detection doesn't access credentials | None |
|
||||
|
||||
**Security Best Practices:**
|
||||
|
||||
- Use trusted, secure DNS resolvers (e.g., 1.1.1.1, 8.8.8.8)
|
||||
- Enable DNSSEC validation if possible
|
||||
- Monitor detection error rates for anomalies
|
||||
@@ -1043,11 +1107,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** Currently supports 10 major DNS providers
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Custom DNS providers won't be auto-detected
|
||||
- Niche/regional providers not in pattern database
|
||||
- Self-hosted DNS servers not recognized
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Use manual provider selection
|
||||
- Request provider pattern addition via GitHub issue
|
||||
- Contribute pattern via pull request
|
||||
@@ -1061,15 +1127,18 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** Some hosting providers use shared nameserver pools
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Nameserver patterns may be ambiguous
|
||||
- Detection may suggest incorrect provider
|
||||
- Confidence scoring may be lower
|
||||
|
||||
**Example:**
|
||||
|
||||
- Some resellers use white-labeled nameservers
|
||||
- Shared hosting platforms with generic nameserver names
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Verify detection result against your account
|
||||
- Use manual selection if detection is incorrect
|
||||
- Report ambiguous patterns for improvement
|
||||
@@ -1081,11 +1150,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** DNS changes take up to 48 hours to propagate globally
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Detection may show old/outdated provider
|
||||
- Recent migrations not immediately reflected
|
||||
- Newly registered domains may fail detection
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Wait for DNS propagation to complete
|
||||
- Check nameservers with `dig` or `nslookup`
|
||||
- Use manual selection during migration period
|
||||
@@ -1098,11 +1169,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** Requires DNS connectivity to function
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Offline/airgapped environments cannot use auto-detection
|
||||
- Network issues cause detection failures
|
||||
- DNS server outages prevent detection
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Use manual provider selection in offline environments
|
||||
- Ensure DNS connectivity for auto-detection
|
||||
- Detection failure doesn't block manual configuration
|
||||
@@ -1114,11 +1187,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** Results cached for 1 hour
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Recent DNS changes not immediately reflected
|
||||
- Cache may show outdated information
|
||||
- No manual cache invalidation
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Wait 60 minutes for cache expiration
|
||||
- Restart Charon to clear cache immediately
|
||||
- Use manual selection to override cached result
|
||||
@@ -1132,11 +1207,13 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
**Limitation:** Only one domain detected at a time
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Cannot detect multiple domains in one request
|
||||
- API requires separate call per domain
|
||||
- Bulk operations require iteration
|
||||
|
||||
**Workaround:**
|
||||
|
||||
- Implement client-side batching
|
||||
- Leverage cache for repeated domains
|
||||
- Use async/parallel API calls
|
||||
@@ -1150,17 +1227,20 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### 1. Verify Detection Results
|
||||
|
||||
**Always Review Before Proceeding:**
|
||||
|
||||
- ✅ Check detected provider name matches your expectation
|
||||
- ✅ Review nameserver list for accuracy
|
||||
- ✅ Verify confidence level is acceptable
|
||||
- ✅ Compare with your DNS account if uncertain
|
||||
|
||||
**Why:**
|
||||
|
||||
- Detection is not 100% accurate
|
||||
- DNS configuration can be complex
|
||||
- Wrong provider = certificate issuance failure
|
||||
|
||||
**Example Review Checklist:**
|
||||
|
||||
```
|
||||
✓ Provider name: "Cloudflare" ← Correct?
|
||||
✓ Nameservers: ns1.cloudflare.com ← Recognized?
|
||||
@@ -1183,6 +1263,7 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
| Development | Low/Any | Manual verify |
|
||||
|
||||
**Why:**
|
||||
|
||||
- Production certificate failures are costly
|
||||
- High confidence = strong, unambiguous match
|
||||
- Medium/Low = requires human verification
|
||||
@@ -1192,12 +1273,14 @@ curl https://charon.example.com/api/v1/dns-providers/detection-patterns \
|
||||
### 3. Keep Manual Override Available
|
||||
|
||||
**Always Provide Manual Selection:**
|
||||
|
||||
- Don't remove "Select Manually" button
|
||||
- Auto-detection is a convenience, not requirement
|
||||
- Users may know better than detection algorithm
|
||||
- Edge cases always exist
|
||||
|
||||
**UI Pattern:**
|
||||
|
||||
```
|
||||
✓ Cloudflare detected (High confidence)
|
||||
[✓ Use Cloudflare] [Select Manually] ← Keep both options!
|
||||
@@ -1224,6 +1307,7 @@ curl -X POST https://charon-dev.internal/api/v1/dns-providers/detect \
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Identify detection issues early
|
||||
- Verify your DNS setup is detectable
|
||||
- Test integration before production use
|
||||
@@ -1233,18 +1317,21 @@ curl -X POST https://charon-dev.internal/api/v1/dns-providers/detect \
|
||||
### 5. Monitor Detection Success Rates
|
||||
|
||||
**Track Metrics:**
|
||||
|
||||
- Detection success rate (detected vs. not detected)
|
||||
- Confidence distribution (high/medium/low/none)
|
||||
- Manual override rate (users choosing manual selection)
|
||||
- Detection errors (timeouts, failures)
|
||||
|
||||
**Use Metrics to:**
|
||||
|
||||
- Identify common providers not in database
|
||||
- Detect DNS configuration issues
|
||||
- Improve pattern database
|
||||
- Optimize cache hit rate
|
||||
|
||||
**Example Monitoring:**
|
||||
|
||||
```
|
||||
Detection Stats (Last 7 Days):
|
||||
- Total detections: 1,234
|
||||
@@ -1261,6 +1348,7 @@ Detection Stats (Last 7 Days):
|
||||
**Help Improve Detection:**
|
||||
|
||||
When detection fails or is incorrect:
|
||||
|
||||
1. ✅ Note the domain (if not sensitive)
|
||||
2. ✅ Check actual nameservers: `dig NS domain.com +short`
|
||||
3. ✅ Note expected provider
|
||||
@@ -1268,6 +1356,7 @@ When detection fails or is incorrect:
|
||||
5. ✅ Report via GitHub issue
|
||||
|
||||
**Example GitHub Issue:**
|
||||
|
||||
```markdown
|
||||
**Title:** Detection fails for Linode DNS
|
||||
|
||||
@@ -1283,6 +1372,7 @@ Add pattern: "linode.com" → "linode"
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Helps other users with same provider
|
||||
- Improves detection accuracy
|
||||
- Expands supported provider list
|
||||
@@ -1298,16 +1388,19 @@ Add pattern: "linode.com" → "linode"
|
||||
- ✅ After 1 hour: Fresh DNS lookup
|
||||
|
||||
**Considerations:**
|
||||
|
||||
- Don't rely on immediate updates after DNS changes
|
||||
- Wait 60 minutes or restart Charon after migration
|
||||
- Cache improves performance—embrace it!
|
||||
|
||||
**When Cache Matters:**
|
||||
|
||||
- DNS provider migration in progress
|
||||
- Testing detection repeatedly
|
||||
- Debugging detection issues
|
||||
|
||||
**Cache Doesn't Affect:**
|
||||
|
||||
- Manual provider selection
|
||||
- Certificate issuance
|
||||
- Existing proxy host configurations
|
||||
@@ -1319,42 +1412,49 @@ Add pattern: "linode.com" → "linode"
|
||||
### Planned Features
|
||||
|
||||
**1. Custom Nameserver Pattern Definitions**
|
||||
|
||||
- Allow users to add custom provider patterns
|
||||
- Define patterns via Web UI or configuration file
|
||||
- Support for internal/private DNS providers
|
||||
- Pattern validation and testing tools
|
||||
|
||||
**2. Detection History and Statistics**
|
||||
|
||||
- View past detection results
|
||||
- Success/failure rates per provider
|
||||
- Confidence distribution charts
|
||||
- Most common providers in your environment
|
||||
|
||||
**3. Support for Additional DNS Providers**
|
||||
|
||||
- Add more regional providers
|
||||
- Support for niche/specialized DNS services
|
||||
- Community-contributed pattern library
|
||||
- Automatic pattern updates
|
||||
|
||||
**4. Detection Caching Configuration**
|
||||
|
||||
- Configurable cache TTL (currently fixed at 1 hour)
|
||||
- Per-provider cache settings
|
||||
- Manual cache invalidation API
|
||||
- Cache statistics dashboard
|
||||
|
||||
**5. Batch Domain Detection**
|
||||
|
||||
- Detect multiple domains in one API call
|
||||
- Bulk import with auto-detection
|
||||
- CSV upload with detection report
|
||||
- Parallel detection processing
|
||||
|
||||
**6. Enhanced Confidence Scoring**
|
||||
|
||||
- Machine learning-based scoring
|
||||
- Historical accuracy feedback
|
||||
- Provider-specific confidence thresholds
|
||||
- Confidence explanation details
|
||||
|
||||
**7. Detection Webhooks**
|
||||
|
||||
- Notify external systems of detection results
|
||||
- Integrate with automation workflows
|
||||
- Detection event logging
|
||||
@@ -1365,6 +1465,7 @@ Add pattern: "linode.com" → "linode"
|
||||
### Community Contributions
|
||||
|
||||
**We Welcome:**
|
||||
|
||||
- 🌟 New provider pattern additions
|
||||
- 🐛 Bug reports for incorrect detections
|
||||
- 💡 Feature requests and ideas
|
||||
@@ -1374,6 +1475,7 @@ Add pattern: "linode.com" → "linode"
|
||||
**How to Contribute:**
|
||||
|
||||
**Add a Provider Pattern:**
|
||||
|
||||
```bash
|
||||
# 1. Fork repository
|
||||
# 2. Edit: backend/internal/services/dns_detection_service.go
|
||||
@@ -1391,11 +1493,13 @@ var BuiltInNameservers = map[string]string{
|
||||
```
|
||||
|
||||
**Report Detection Issues:**
|
||||
- GitHub Issues: https://github.com/Wikid82/Charon/issues
|
||||
|
||||
- GitHub Issues: <https://github.com/Wikid82/Charon/issues>
|
||||
- Label: `enhancement`, `dns-detection`
|
||||
- Provide: Domain example, nameservers, expected provider
|
||||
|
||||
**Share Use Cases:**
|
||||
|
||||
- How are you using auto-detection?
|
||||
- What workflows does it enable?
|
||||
- What features would be helpful?
|
||||
@@ -1405,16 +1509,18 @@ var BuiltInNameservers = map[string]string{
|
||||
### Feedback Welcome
|
||||
|
||||
**Help Us Improve:**
|
||||
|
||||
- Share your experience with auto-detection
|
||||
- Report detection accuracy issues
|
||||
- Suggest new provider patterns
|
||||
- Request feature enhancements
|
||||
|
||||
**Contact:**
|
||||
- GitHub Issues: https://github.com/Wikid82/Charon/issues
|
||||
- GitHub Discussions: https://github.com/Wikid82/Charon/discussions
|
||||
- Documentation: https://docs.charon.example.com
|
||||
- Community: https://community.charon.example.com
|
||||
|
||||
- GitHub Issues: <https://github.com/Wikid82/Charon/issues>
|
||||
- GitHub Discussions: <https://github.com/Wikid82/Charon/discussions>
|
||||
- Documentation: <https://docs.charon.example.com>
|
||||
- Community: <https://community.charon.example.com>
|
||||
|
||||
---
|
||||
|
||||
@@ -1433,6 +1539,7 @@ var BuiltInNameservers = map[string]string{
|
||||
### Version 1.0.0 (January 2026)
|
||||
|
||||
**Initial Release**
|
||||
|
||||
- ✨ DNS provider auto-detection for 10+ major providers
|
||||
- 🚀 Web UI integration with ProxyHost form
|
||||
- 🔌 RESTful API endpoints (`/detect`, `/detection-patterns`)
|
||||
@@ -1445,6 +1552,7 @@ var BuiltInNameservers = map[string]string{
|
||||
- ♿ Accessibility: ARIA labels, keyboard navigation
|
||||
|
||||
**Supported Providers:**
|
||||
|
||||
- Cloudflare
|
||||
- Amazon Route 53
|
||||
- DigitalOcean
|
||||
@@ -1457,6 +1565,7 @@ var BuiltInNameservers = map[string]string{
|
||||
- DNSimple
|
||||
|
||||
**Technical Details:**
|
||||
|
||||
- Pattern-based nameserver matching
|
||||
- Automatic wildcard domain normalization
|
||||
- Thread-safe cache implementation
|
||||
@@ -1503,17 +1612,20 @@ A: Typically 100-200ms for first detection, <1ms for cached results.
|
||||
## Support
|
||||
|
||||
**Questions or Issues?**
|
||||
- 📖 Documentation: https://docs.charon.example.com
|
||||
- 🐛 GitHub Issues: https://github.com/Wikid82/Charon/issues
|
||||
- 💬 GitHub Discussions: https://github.com/Wikid82/Charon/discussions
|
||||
- 👥 Community Forum: https://community.charon.example.com
|
||||
|
||||
- 📖 Documentation: <https://docs.charon.example.com>
|
||||
- 🐛 GitHub Issues: <https://github.com/Wikid82/Charon/issues>
|
||||
- 💬 GitHub Discussions: <https://github.com/Wikid82/Charon/discussions>
|
||||
- 👥 Community Forum: <https://community.charon.example.com>
|
||||
|
||||
**Feature Requests:**
|
||||
|
||||
- Submit via GitHub Issues with label `enhancement`
|
||||
- Describe your use case and desired functionality
|
||||
- Include examples and expected behavior
|
||||
|
||||
**Bug Reports:**
|
||||
|
||||
- Submit via GitHub Issues with label `bug`
|
||||
- Include: Domain (if not sensitive), nameservers, expected vs. actual result
|
||||
- Attach detection API response if available
|
||||
|
||||
@@ -133,6 +133,7 @@ Every encrypted credential stores its **key version** alongside the ciphertext.
|
||||
- **Rotation tracking**: Verify rotation completed successfully
|
||||
|
||||
**Example**:
|
||||
|
||||
- Before rotation: All 15 DNS providers have `key_version = 1`
|
||||
- After rotation: All 15 DNS providers have `key_version = 2`
|
||||
|
||||
@@ -153,11 +154,13 @@ CHARON_ENCRYPTION_KEY_V2="OlderK1234567890OlderK1234567890OlderK1=="
|
||||
```
|
||||
|
||||
**Key Format Requirements**:
|
||||
|
||||
- **Length**: 32 bytes (before base64 encoding)
|
||||
- **Encoding**: Base64-encoded
|
||||
- **Generation**: Use cryptographically secure random number generator
|
||||
|
||||
**Generate a new key**:
|
||||
|
||||
```bash
|
||||
# Using OpenSSL
|
||||
openssl rand -base64 32
|
||||
@@ -182,6 +185,7 @@ node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
||||
### Permission Requirements
|
||||
|
||||
**Admin Role Required**: Only users with `role = "admin"` can:
|
||||
|
||||
- View encryption status
|
||||
- Trigger key rotation
|
||||
- Validate key configuration
|
||||
@@ -220,6 +224,7 @@ The Encryption Management page includes:
|
||||
**What it shows**: The active key version in use.
|
||||
|
||||
**Possible values**:
|
||||
|
||||
- `Version 1` — Initial key (default state)
|
||||
- `Version 2` — After first rotation
|
||||
- `Version 3+` — After subsequent rotations
|
||||
@@ -241,6 +246,7 @@ The Encryption Management page includes:
|
||||
**Example**: `3 Providers` — Three providers still use legacy keys.
|
||||
|
||||
**What to check**:
|
||||
|
||||
- Should be **0** immediately after successful rotation
|
||||
- If non-zero after rotation, check audit logs for errors
|
||||
|
||||
@@ -249,6 +255,7 @@ The Encryption Management page includes:
|
||||
**What it shows**: Whether `CHARON_ENCRYPTION_KEY_NEXT` is configured.
|
||||
|
||||
**Possible values**:
|
||||
|
||||
- ✅ **Configured** — Ready for rotation
|
||||
- ❌ **Not Configured** — Cannot rotate (next key not set)
|
||||
|
||||
@@ -284,6 +291,7 @@ Before rotating keys, ensure:
|
||||
**Action**: Configure `CHARON_ENCRYPTION_KEY_NEXT` environment variable.
|
||||
|
||||
**Docker Compose Example**:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
charon:
|
||||
@@ -293,6 +301,7 @@ services:
|
||||
```
|
||||
|
||||
**Docker CLI Example**:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-e CHARON_ENCRYPTION_KEY="ABcdEF1234567890ABcdEF1234567890ABCDEFGH=" \
|
||||
@@ -301,6 +310,7 @@ docker run -d \
|
||||
```
|
||||
|
||||
**Kubernetes Example**:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -332,12 +342,14 @@ kubectl rollout restart deployment/charon
|
||||
**What happens**: Charon loads both current and next keys into memory.
|
||||
|
||||
**Verification**:
|
||||
|
||||
```bash
|
||||
# Check logs for successful startup
|
||||
docker logs charon 2>&1 | grep "encryption"
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
{"level":"info","msg":"Encryption keys loaded: current + next configured"}
|
||||
```
|
||||
@@ -347,6 +359,7 @@ Expected output:
|
||||
**Action**: Click **"Validate Configuration"** button in the Encryption Management UI.
|
||||
|
||||
**Alternative (API)**:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
@@ -355,6 +368,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
**What happens**: Charon tests round-trip encryption with all configured keys (current, next, legacy).
|
||||
|
||||
**Success response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "valid",
|
||||
@@ -370,17 +384,20 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
**Action**: Click **"Rotate Encryption Key"** button in the Encryption Management UI.
|
||||
|
||||
**Confirmation dialog**:
|
||||
|
||||
- Review the warning: "This will re-encrypt all DNS provider credentials with the new key. This operation cannot be undone."
|
||||
- Check **"I understand"** checkbox
|
||||
- Click **"Start Rotation"**
|
||||
|
||||
**Alternative (API)**:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
```
|
||||
|
||||
**What happens**:
|
||||
|
||||
1. Charon fetches all DNS providers from the database
|
||||
2. For each provider:
|
||||
- Decrypts credentials with current key
|
||||
@@ -390,6 +407,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
3. Returns detailed rotation result
|
||||
|
||||
**Success response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_providers": 15,
|
||||
@@ -410,17 +428,20 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
**Action**: Refresh the Encryption Management page.
|
||||
|
||||
**What to check**:
|
||||
|
||||
- ✅ **Current Key Version**: Should now show `Version 2`
|
||||
- ✅ **Providers Updated**: Should show `15 Providers` (your total count)
|
||||
- ✅ **Providers Outdated**: Should show `0 Providers`
|
||||
|
||||
**Alternative (API)**:
|
||||
|
||||
```bash
|
||||
curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
```
|
||||
|
||||
**Expected response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"current_version": 2,
|
||||
@@ -439,12 +460,14 @@ curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
**Action**: Update environment variables to make the new key permanent.
|
||||
|
||||
**Before**:
|
||||
|
||||
```bash
|
||||
CHARON_ENCRYPTION_KEY="ABcdEF1234567890ABcdEF1234567890ABCDEFGH=" # Old key
|
||||
CHARON_ENCRYPTION_KEY_NEXT="XyZaBcDeF1234567890XyZaBcDeF1234567890XY=" # New key
|
||||
```
|
||||
|
||||
**After**:
|
||||
|
||||
```bash
|
||||
CHARON_ENCRYPTION_KEY="XyZaBcDeF1234567890XyZaBcDeF1234567890XY=" # New key (promoted)
|
||||
CHARON_ENCRYPTION_KEY_V1="ABcdEF1234567890ABcdEF1234567890ABCDEFGH=" # Old key (kept as legacy)
|
||||
@@ -464,11 +487,13 @@ docker-compose restart charon
|
||||
**What happens**: Charon now uses the new key for future encryptions and keeps the old key for fallback.
|
||||
|
||||
**Verification**:
|
||||
|
||||
```bash
|
||||
docker logs charon 2>&1 | grep "encryption"
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
{"level":"info","msg":"Encryption keys loaded: current + 1 legacy keys"}
|
||||
```
|
||||
@@ -484,16 +509,19 @@ Expected output:
|
||||
### Monitoring Rotation Progress
|
||||
|
||||
**During rotation**:
|
||||
|
||||
- The UI shows a loading overlay with "Rotating..." message
|
||||
- The rotation button is disabled
|
||||
- You'll see a progress toast notification
|
||||
|
||||
**After rotation**:
|
||||
|
||||
- Success toast appears with provider count and duration
|
||||
- Status cards update immediately
|
||||
- Audit log entry is created
|
||||
|
||||
**If rotation takes longer than expected**:
|
||||
|
||||
- Check the backend logs: `docker logs charon -f`
|
||||
- Look for errors like "Failed to decrypt provider X credentials"
|
||||
- See [Troubleshooting](#troubleshooting) section
|
||||
@@ -505,6 +533,7 @@ Expected output:
|
||||
### Why Validate?
|
||||
|
||||
Validation tests that all configured keys work correctly **before** triggering rotation. This prevents:
|
||||
|
||||
- ❌ Broken keys being used for rotation
|
||||
- ❌ Credentials becoming inaccessible
|
||||
- ❌ Failed rotations due to corrupted keys
|
||||
@@ -512,6 +541,7 @@ Validation tests that all configured keys work correctly **before** triggering r
|
||||
### When to Validate
|
||||
|
||||
Run validation:
|
||||
|
||||
- ✅ **Before** every key rotation
|
||||
- ✅ **After** changing environment variables
|
||||
- ✅ **After** restoring from backup
|
||||
@@ -520,11 +550,13 @@ Run validation:
|
||||
### How to Validate
|
||||
|
||||
**Via UI**:
|
||||
|
||||
1. Go to **Security** → **Encryption Management**
|
||||
2. Click **"Validate Configuration"** button
|
||||
3. Wait for validation to complete (usually < 1 second)
|
||||
|
||||
**Via API**:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
@@ -554,6 +586,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
**UI**: Green success toast: "Key configuration is valid and ready for rotation"
|
||||
|
||||
**API Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "valid",
|
||||
@@ -572,6 +605,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
**UI**: Red error toast: "Key configuration validation failed. Check errors below."
|
||||
|
||||
**API Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "invalid",
|
||||
@@ -587,6 +621,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
```
|
||||
|
||||
**Common errors**:
|
||||
|
||||
- `"decryption failed"` — Key is corrupted or not base64-encoded correctly
|
||||
- `"key too short"` — Key is not 32 bytes after base64 decoding
|
||||
- `"invalid base64"` — Key contains invalid base64 characters
|
||||
@@ -596,6 +631,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
**Error**: `"next_key: decryption failed"`
|
||||
|
||||
**Fix**:
|
||||
|
||||
1. Regenerate the next key: `openssl rand -base64 32`
|
||||
2. Update `CHARON_ENCRYPTION_KEY_NEXT` environment variable
|
||||
3. Restart Charon
|
||||
@@ -604,6 +640,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
**Error**: `"key too short"`
|
||||
|
||||
**Fix**:
|
||||
|
||||
1. Ensure you're generating 32 bytes: `openssl rand -base64 32` (not `openssl rand 32`)
|
||||
2. Verify base64 encoding is correct
|
||||
3. Update environment variable
|
||||
@@ -612,6 +649,7 @@ Charon performs round-trip encryption for each configured key:
|
||||
**Error**: `"invalid base64"`
|
||||
|
||||
**Fix**:
|
||||
|
||||
1. Check for extra whitespace or newlines in the key
|
||||
2. Ensure the key is properly quoted in docker-compose.yml
|
||||
3. Re-copy the key carefully
|
||||
@@ -625,11 +663,13 @@ Charon performs round-trip encryption for each configured key:
|
||||
### Accessing Audit History
|
||||
|
||||
**Via UI**:
|
||||
|
||||
1. Go to **Security** → **Encryption Management**
|
||||
2. Scroll to the **Rotation History** section at the bottom
|
||||
3. View paginated list of rotation events
|
||||
|
||||
**Via API**:
|
||||
|
||||
```bash
|
||||
curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=20" \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
@@ -646,6 +686,7 @@ Charon logs the following encryption-related audit events:
|
||||
**When**: Immediately when rotation is triggered
|
||||
|
||||
**Details**:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T10:00:00Z",
|
||||
@@ -666,6 +707,7 @@ Charon logs the following encryption-related audit events:
|
||||
**When**: After all providers are successfully re-encrypted
|
||||
|
||||
**Details**:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T10:00:02Z",
|
||||
@@ -688,6 +730,7 @@ Charon logs the following encryption-related audit events:
|
||||
**When**: If rotation encounters critical errors
|
||||
|
||||
**Details**:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T10:05:00Z",
|
||||
@@ -709,6 +752,7 @@ Charon logs the following encryption-related audit events:
|
||||
**When**: After successful validation
|
||||
|
||||
**Details**:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T09:55:00Z",
|
||||
@@ -728,6 +772,7 @@ Charon logs the following encryption-related audit events:
|
||||
**When**: If validation detects issues
|
||||
|
||||
**Details**:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T09:50:00Z",
|
||||
@@ -742,6 +787,7 @@ Charon logs the following encryption-related audit events:
|
||||
### Filtering History
|
||||
|
||||
**By page**:
|
||||
|
||||
```bash
|
||||
curl "https://your-charon-instance/api/v1/admin/encryption/history?page=2&limit=10"
|
||||
```
|
||||
@@ -751,6 +797,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=2&limit=
|
||||
### Exporting History
|
||||
|
||||
**Via API** (JSON):
|
||||
|
||||
```bash
|
||||
curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=1000" \
|
||||
-H "Authorization: Bearer <admin-token>" \
|
||||
@@ -775,16 +822,19 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
### Key Retention Policies
|
||||
|
||||
**Legacy Key Retention**:
|
||||
|
||||
- ✅ Keep legacy keys for **at least 30 days** after rotation
|
||||
- ✅ Extend to **90 days** for high-risk environments
|
||||
- ✅ Never delete legacy keys immediately after rotation
|
||||
|
||||
**Why**:
|
||||
|
||||
- Allows rollback if issues are discovered
|
||||
- Supports disaster recovery from old backups
|
||||
- Provides time to verify rotation success
|
||||
|
||||
**After Retention Period**:
|
||||
|
||||
1. Verify no issues occurred during retention window
|
||||
2. Remove legacy key from environment variables
|
||||
3. Restart Charon to apply changes
|
||||
@@ -793,24 +843,30 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
### Backup Procedures
|
||||
|
||||
**Before Every Rotation**:
|
||||
|
||||
1. **Backup the database**:
|
||||
|
||||
```bash
|
||||
docker exec charon_db pg_dump -U charon charon_db > backup_before_rotation_$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
2. **Backup environment variables**:
|
||||
|
||||
```bash
|
||||
cp docker-compose.yml docker-compose.yml.backup_$(date +%Y%m%d)
|
||||
```
|
||||
|
||||
3. **Test backup restoration**:
|
||||
|
||||
```bash
|
||||
# Restore database
|
||||
docker exec -i charon_db psql -U charon charon_db < backup_before_rotation_20260104.sql
|
||||
```
|
||||
|
||||
**After Rotation**:
|
||||
|
||||
1. **Backup the new state**:
|
||||
|
||||
```bash
|
||||
docker exec charon_db pg_dump -U charon charon_db > backup_after_rotation_$(date +%Y%m%d).sql
|
||||
```
|
||||
@@ -823,6 +879,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
### Testing in Staging First
|
||||
|
||||
**Before rotating production keys**:
|
||||
|
||||
1. ✅ Deploy exact production configuration to staging
|
||||
2. ✅ Perform full rotation in staging
|
||||
3. ✅ Verify all DNS providers still work
|
||||
@@ -832,6 +889,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
7. ✅ Apply same procedure to production
|
||||
|
||||
**Staging checklist**:
|
||||
|
||||
- [ ] Same Charon version as production
|
||||
- [ ] Same number of DNS providers
|
||||
- [ ] Same encryption key length and format
|
||||
@@ -847,17 +905,21 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Scenario**: Rotation just completed but providers are failing.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. **Restore database from pre-rotation backup**:
|
||||
|
||||
```bash
|
||||
docker exec -i charon_db psql -U charon charon_db < backup_before_rotation_20260104.sql
|
||||
```
|
||||
|
||||
2. **Revert environment variables**:
|
||||
|
||||
```bash
|
||||
cp docker-compose.yml.backup_20260104 docker-compose.yml
|
||||
```
|
||||
|
||||
3. **Restart Charon**:
|
||||
|
||||
```bash
|
||||
docker-compose restart charon
|
||||
```
|
||||
@@ -872,7 +934,9 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Scenario**: Issues discovered hours or days after rotation.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. **Keep new key as legacy**:
|
||||
|
||||
```bash
|
||||
CHARON_ENCRYPTION_KEY="<old-key>" # Revert to old key
|
||||
CHARON_ENCRYPTION_KEY_V2="<new-key>" # Keep new key as legacy
|
||||
@@ -893,24 +957,28 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
### Security Considerations
|
||||
|
||||
**Key Storage**:
|
||||
|
||||
- ❌ **NEVER** commit keys to version control
|
||||
- ✅ Use environment variables or secrets manager
|
||||
- ✅ Restrict access to key values (need-to-know basis)
|
||||
- ✅ Audit access to secrets manager
|
||||
|
||||
**Key Generation**:
|
||||
|
||||
- ✅ Always use cryptographically secure RNG (`openssl`, `secrets`, `crypto`)
|
||||
- ❌ Never use predictable sources (`date`, `rand()`, keyboard mashing)
|
||||
- ✅ Generate keys on secure, trusted systems
|
||||
- ✅ Never reuse keys across environments (prod vs staging)
|
||||
|
||||
**Key Transmission**:
|
||||
|
||||
- ✅ Use encrypted channels (SSH, TLS) to transmit keys
|
||||
- ❌ Never send keys via email, Slack, or unencrypted chat
|
||||
- ✅ Use secrets managers with RBAC (e.g., Vault, AWS Secrets Manager)
|
||||
- ✅ Rotate keys immediately if transmission is compromised
|
||||
|
||||
**Access Control**:
|
||||
|
||||
- ✅ Limit key rotation to admin users only
|
||||
- ✅ Require MFA for admin accounts
|
||||
- ✅ Audit all key-related operations
|
||||
@@ -927,11 +995,13 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Symptom**: "Rotate Encryption Key" button is grayed out.
|
||||
|
||||
**Possible causes**:
|
||||
|
||||
1. ❌ Next key not configured
|
||||
2. ❌ Not logged in as admin
|
||||
3. ❌ Rotation already in progress
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. Check **Next Key Status** — should show "Configured"
|
||||
2. Verify you're logged in as admin (check user menu)
|
||||
3. Wait for in-progress rotation to complete
|
||||
@@ -942,12 +1012,15 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Symptom**: Toast shows "Warning: 3 providers failed to rotate."
|
||||
|
||||
**Possible causes**:
|
||||
|
||||
1. ❌ Corrupted credentials in database
|
||||
2. ❌ Missing key versions
|
||||
3. ❌ Database transaction errors
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Check audit logs** for specific errors:
|
||||
|
||||
```bash
|
||||
curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1" \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
@@ -972,12 +1045,15 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Symptom**: After promoting next key, Charon won't start or credentials fail.
|
||||
|
||||
**Error log**:
|
||||
|
||||
```
|
||||
{"level":"fatal","msg":"CHARON_ENCRYPTION_KEY not set"}
|
||||
```
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Check environment variables**:
|
||||
|
||||
```bash
|
||||
docker exec charon env | grep CHARON_ENCRYPTION
|
||||
```
|
||||
@@ -988,6 +1064,7 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
- Verify base64 encoding is correct
|
||||
|
||||
3. **Restart with corrected config**:
|
||||
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
@@ -998,20 +1075,24 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Symptom**: Status shows "Providers Outdated: 15" even after rotation.
|
||||
|
||||
**Possible causes**:
|
||||
|
||||
1. ❌ Rotation didn't complete successfully
|
||||
2. ❌ Database rollback occurred
|
||||
3. ❌ Frontend cache showing stale data
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Refresh the page** (hard refresh: Ctrl+Shift+R)
|
||||
|
||||
2. **Check API directly**:
|
||||
|
||||
```bash
|
||||
curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
```
|
||||
|
||||
3. **Verify database state**:
|
||||
|
||||
```sql
|
||||
SELECT key_version, COUNT(*) FROM dns_providers GROUP BY key_version;
|
||||
```
|
||||
@@ -1025,17 +1106,20 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Error**: `"v1: decryption failed"`
|
||||
|
||||
**Possible causes**:
|
||||
|
||||
1. ❌ Key was changed accidentally
|
||||
2. ❌ Key is corrupted
|
||||
3. ❌ Wrong key assigned to V1
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Identify the correct key**:
|
||||
- Check your key rotation history
|
||||
- Review backup files
|
||||
- Consult secrets manager logs
|
||||
|
||||
2. **Update environment variable**:
|
||||
|
||||
```bash
|
||||
CHARON_ENCRYPTION_KEY_V1="<correct-old-key>"
|
||||
```
|
||||
@@ -1052,27 +1136,33 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
**Symptom**: Rotation running for > 5 minutes with many providers.
|
||||
|
||||
**Expected duration**:
|
||||
|
||||
- 1-10 providers: < 5 seconds
|
||||
- 10-50 providers: < 30 seconds
|
||||
- 50-100 providers: < 2 minutes
|
||||
|
||||
**Possible causes**:
|
||||
|
||||
1. ❌ Database performance issues
|
||||
2. ❌ Database locks or contention
|
||||
3. ❌ Network issues (if database is remote)
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Check backend logs**:
|
||||
|
||||
```bash
|
||||
docker logs charon -f | grep "rotation"
|
||||
```
|
||||
|
||||
2. **Look for slow queries**:
|
||||
|
||||
```bash
|
||||
docker logs charon | grep "slow query"
|
||||
```
|
||||
|
||||
3. **Check database health**:
|
||||
|
||||
```bash
|
||||
docker exec charon_db pg_stat_activity
|
||||
```
|
||||
@@ -1086,11 +1176,13 @@ If rotation fails or issues are discovered, follow this rollback procedure:
|
||||
If you encounter issues not covered here:
|
||||
|
||||
1. **Check the logs**:
|
||||
|
||||
```bash
|
||||
docker logs charon -f
|
||||
```
|
||||
|
||||
2. **Enable debug logging** (if needed):
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- LOG_LEVEL=debug
|
||||
@@ -1123,12 +1215,14 @@ All encryption management endpoints require **admin authentication**.
|
||||
**Authentication**: Required (admin only)
|
||||
|
||||
**Request**:
|
||||
|
||||
```bash
|
||||
curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
```
|
||||
|
||||
**Success Response** (HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"current_version": 2,
|
||||
@@ -1143,6 +1237,7 @@ curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
|
||||
- `current_version` (int): Active key version (1, 2, 3, etc.)
|
||||
- `next_key_configured` (bool): Whether `CHARON_ENCRYPTION_KEY_NEXT` is set
|
||||
- `legacy_key_count` (int): Number of legacy keys (V1-V10) configured
|
||||
@@ -1151,6 +1246,7 @@ curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
- `providers_on_older_versions` (int): Count needing rotation
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
- **401 Unauthorized**: Missing or invalid token
|
||||
- **403 Forbidden**: Non-admin user
|
||||
- **500 Internal Server Error**: Database or encryption service error
|
||||
@@ -1166,10 +1262,12 @@ curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
**Authentication**: Required (admin only)
|
||||
|
||||
**Prerequisites**:
|
||||
|
||||
- `CHARON_ENCRYPTION_KEY_NEXT` must be configured
|
||||
- Application must be restarted to load next key
|
||||
|
||||
**Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
-H "Authorization: Bearer <admin-token>" \
|
||||
@@ -1177,6 +1275,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
```
|
||||
|
||||
**Success Response** (HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"total_providers": 15,
|
||||
@@ -1191,6 +1290,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
```
|
||||
|
||||
**Partial Success Response** (HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"total_providers": 15,
|
||||
@@ -1205,6 +1305,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
|
||||
- `total_providers` (int): Total DNS providers in database
|
||||
- `success_count` (int): Providers successfully re-encrypted
|
||||
- `failure_count` (int): Providers that failed re-encryption
|
||||
@@ -1215,17 +1316,21 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
- `new_key_version` (int): New key version after rotation
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
- **400 Bad Request**: `CHARON_ENCRYPTION_KEY_NEXT` not configured
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Next key not configured. Set CHARON_ENCRYPTION_KEY_NEXT and restart."
|
||||
}
|
||||
```
|
||||
|
||||
- **401 Unauthorized**: Missing or invalid token
|
||||
- **403 Forbidden**: Non-admin user
|
||||
- **500 Internal Server Error**: Critical failure during rotation
|
||||
|
||||
**Audit Events Created**:
|
||||
|
||||
- `encryption_key_rotation_started` — When rotation begins
|
||||
- `encryption_key_rotation_completed` — When rotation succeeds
|
||||
- `encryption_key_rotation_failed` — When rotation fails
|
||||
@@ -1241,6 +1346,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/rotate \
|
||||
**Authentication**: Required (admin only)
|
||||
|
||||
**Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
-H "Authorization: Bearer <admin-token>" \
|
||||
@@ -1248,6 +1354,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
```
|
||||
|
||||
**Success Response** (HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "valid",
|
||||
@@ -1264,6 +1371,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
```
|
||||
|
||||
**Failure Response** (HTTP 400):
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "invalid",
|
||||
@@ -1279,6 +1387,7 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
|
||||
- `status` (string): `"valid"` or `"invalid"`
|
||||
- `keys_tested` (int): Total keys tested
|
||||
- `message` (string): Human-readable summary
|
||||
@@ -1286,11 +1395,13 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
- `errors` (array): List of validation errors (if any)
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
- **401 Unauthorized**: Missing or invalid token
|
||||
- **403 Forbidden**: Non-admin user
|
||||
- **500 Internal Server Error**: Validation service error
|
||||
|
||||
**Audit Events Created**:
|
||||
|
||||
- `encryption_key_validation_success` — When validation passes
|
||||
- `encryption_key_validation_failed` — When validation fails
|
||||
|
||||
@@ -1305,16 +1416,19 @@ curl -X POST https://your-charon-instance/api/v1/admin/encryption/validate \
|
||||
**Authentication**: Required (admin only)
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `page` (int, optional): Page number (default: 1)
|
||||
- `limit` (int, optional): Results per page (default: 20, max: 100)
|
||||
|
||||
**Request**:
|
||||
|
||||
```bash
|
||||
curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=20" \
|
||||
-H "Authorization: Bearer <admin-token>"
|
||||
```
|
||||
|
||||
**Success Response** (HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
@@ -1355,6 +1469,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
|
||||
- `events` (array): List of audit log entries
|
||||
- `id` (int): Audit log entry ID
|
||||
- `timestamp` (string): ISO 8601 timestamp
|
||||
@@ -1369,6 +1484,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
- `total_pages` (int): Total pages available
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
- **400 Bad Request**: Invalid page or limit parameter
|
||||
- **401 Unauthorized**: Missing or invalid token
|
||||
- **403 Forbidden**: Non-admin user
|
||||
@@ -1381,6 +1497,7 @@ curl "https://your-charon-instance/api/v1/admin/encryption/history?page=1&limit=
|
||||
All encryption management endpoints use **Bearer token authentication**.
|
||||
|
||||
**Obtaining a token**:
|
||||
|
||||
```bash
|
||||
# Login to get token
|
||||
curl -X POST https://your-charon-instance/api/v1/auth/login \
|
||||
@@ -1402,6 +1519,7 @@ curl -X POST https://your-charon-instance/api/v1/auth/login \
|
||||
```
|
||||
|
||||
**Using the token**:
|
||||
|
||||
```bash
|
||||
curl https://your-charon-instance/api/v1/admin/encryption/status \
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
|
||||
@@ -1436,6 +1554,7 @@ Encryption management endpoints are not rate-limited by default, but general API
|
||||
## Summary
|
||||
|
||||
Encryption key rotation is a critical security practice that Charon makes easy with:
|
||||
|
||||
- ✅ **Zero-downtime rotation** — Services remain available throughout the process
|
||||
- ✅ **Multi-key support** — Current + next + legacy keys coexist seamlessly
|
||||
- ✅ **Admin-friendly UI** — No command-line expertise required
|
||||
@@ -1444,6 +1563,7 @@ Encryption key rotation is a critical security practice that Charon makes easy w
|
||||
- ✅ **Validation tools** — Test keys before using them
|
||||
|
||||
**Next Steps**:
|
||||
|
||||
1. Review your organization's key rotation policy
|
||||
2. Schedule your first rotation (test in staging first!)
|
||||
3. Set a recurring reminder for future rotations
|
||||
|
||||
@@ -9,12 +9,14 @@ Multi-Credential per Provider is an advanced feature that allows you to configur
|
||||
### Why Use Multi-Credentials?
|
||||
|
||||
**Security Benefits:**
|
||||
|
||||
- **Zone-level Isolation**: Compromise of one credential doesn't expose all your domains
|
||||
- **Least Privilege Principle**: Each credential can have minimal permissions for only the zones it manages
|
||||
- **Independent Rotation**: Rotate credentials for specific zones without affecting others
|
||||
- **Audit Trail**: Track which credentials were used for certificate operations
|
||||
|
||||
**Business Use Cases:**
|
||||
|
||||
- **Managed Service Providers (MSPs)**: Use separate customer-specific credentials for each client's domains
|
||||
- **Large Enterprises**: Isolate credentials by department, environment, or geographic region
|
||||
- **Multi-Tenant Platforms**: Provide credential isolation between tenants
|
||||
@@ -63,6 +65,7 @@ Multi-Credential Mode:
|
||||
### Decision Criteria
|
||||
|
||||
**Use Multi-Credentials When:**
|
||||
|
||||
- You manage domains for multiple customers or tenants
|
||||
- You need credential isolation for security or compliance
|
||||
- Different teams or departments manage different zones
|
||||
@@ -71,6 +74,7 @@ Multi-Credential Mode:
|
||||
- You need independent credential rotation schedules
|
||||
|
||||
**Use Single Credential When:**
|
||||
|
||||
- You manage a small number of domains under one organization
|
||||
- All domains have the same security requirements
|
||||
- Simpler management is preferred over isolation
|
||||
@@ -108,6 +112,7 @@ Multi-Credential Mode:
|
||||
- A confirmation dialog will appear
|
||||
|
||||
3. **Review Migration Impact**
|
||||
|
||||
```
|
||||
⚠️ IMPORTANT: This action will:
|
||||
- Convert your existing provider credential into a "catch-all" credential
|
||||
@@ -181,6 +186,7 @@ Click the **Add Credential** button in the credential management interface.
|
||||
The zone filter determines which domains this credential will be used for:
|
||||
|
||||
**Option 1: Exact Domain Match**
|
||||
|
||||
```
|
||||
Zone Filter: example.com
|
||||
Matches: example.com, www.example.com, api.example.com
|
||||
@@ -188,6 +194,7 @@ Does NOT Match: subdomain.example.com.au, example.org
|
||||
```
|
||||
|
||||
**Option 2: Wildcard Match**
|
||||
|
||||
```
|
||||
Zone Filter: *.customer-a.com
|
||||
Matches: shop.customer-a.com, api.customer-a.com, *.customer-a.com
|
||||
@@ -195,6 +202,7 @@ Does NOT Match: customer-a.com (root), customer-b.com
|
||||
```
|
||||
|
||||
**Option 3: Multiple Zones (Comma-Separated)**
|
||||
|
||||
```
|
||||
Zone Filter: example.com,api.example.org,*.dev.example.net
|
||||
Matches:
|
||||
@@ -204,6 +212,7 @@ Matches:
|
||||
```
|
||||
|
||||
**Option 4: Catch-All (Empty Filter)**
|
||||
|
||||
```
|
||||
Zone Filter: (leave empty)
|
||||
Matches: Any domain not matched by other credentials
|
||||
@@ -245,6 +254,7 @@ Use Case: Fallback credential for miscellaneous domains
|
||||
#### Validation Rules
|
||||
|
||||
When saving a credential, Charon validates:
|
||||
|
||||
- ✅ Zone filter syntax is correct
|
||||
- ✅ No duplicate exact matches across credentials
|
||||
- ⚠️ Warning if multiple wildcard patterns could overlap
|
||||
@@ -258,6 +268,7 @@ When saving a credential, Charon validates:
|
||||
4. Click **Save Changes**
|
||||
|
||||
**⚠️ Important Notes:**
|
||||
|
||||
- Changing zone filters may affect which credential is used for existing proxy hosts
|
||||
- Charon will re-evaluate credential matching for all proxy hosts after the change
|
||||
- Consider testing in a non-production environment first if making significant changes
|
||||
@@ -309,18 +320,21 @@ When Charon needs to issue or renew a certificate for a domain, it selects a cre
|
||||
Credentials are evaluated in this order:
|
||||
|
||||
**1. Exact Match (Highest Priority)**
|
||||
|
||||
```
|
||||
Zone Filter: example.com
|
||||
Domain: www.example.com → Zone: example.com → ✅ MATCH
|
||||
```
|
||||
|
||||
**2. Wildcard Match**
|
||||
|
||||
```
|
||||
Zone Filter: *.customer-a.com
|
||||
Domain: shop.customer-a.com → Zone: customer-a.com → ✅ MATCH (after exact check fails)
|
||||
```
|
||||
|
||||
**3. Catch-All (Lowest Priority)**
|
||||
|
||||
```
|
||||
Zone Filter: (empty)
|
||||
Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildcard matches)
|
||||
@@ -331,6 +345,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
#### Example 1: MSP with Multiple Customers
|
||||
|
||||
**Configured Credentials:**
|
||||
|
||||
```
|
||||
1. Name: "Customer A Production"
|
||||
Zone Filter: *.customer-a.com
|
||||
@@ -346,6 +361,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
```
|
||||
|
||||
**Domain Matching:**
|
||||
|
||||
- `shop.customer-a.com` → Credential 1 ("Customer A Production")
|
||||
- `api.customer-b.com` → Credential 2 ("Customer B Production")
|
||||
- `example.com` → Credential 3 ("Catch-all")
|
||||
@@ -354,6 +370,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
#### Example 2: Environment Separation
|
||||
|
||||
**Configured Credentials:**
|
||||
|
||||
```
|
||||
1. Name: "Production"
|
||||
Zone Filter: example.com
|
||||
@@ -369,6 +386,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
```
|
||||
|
||||
**Domain Matching:**
|
||||
|
||||
- `www.example.com` → Credential 1 ("Production")
|
||||
- `api.example.com` → Credential 1 ("Production")
|
||||
- `app.staging.example.com` → Credential 2 ("Staging")
|
||||
@@ -378,6 +396,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
#### Example 3: Geographic Separation
|
||||
|
||||
**Configured Credentials:**
|
||||
|
||||
```
|
||||
1. Name: "US Zones"
|
||||
Zone Filter: *.us.example.com
|
||||
@@ -393,6 +412,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
```
|
||||
|
||||
**Domain Matching:**
|
||||
|
||||
- `shop.us.example.com` → Credential 1 ("US Zones")
|
||||
- `api.eu.example.com` → Credential 2 ("EU Zones")
|
||||
- `portal.apac.example.com` → Credential 3 ("APAC Zones")
|
||||
@@ -405,6 +425,7 @@ Domain: anything.com → Zone: anything.com → ✅ MATCH (if no exact or wildca
|
||||
If multiple credentials could match the same zone, Charon uses **first match** based on priority order:
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Credential A: Zone Filter: example.com (Exact)
|
||||
Credential B: Zone Filter: *.example.com (Wildcard)
|
||||
@@ -424,10 +445,12 @@ Match Process:
|
||||
#### Issue: Domain doesn't match any credential
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Certificate issuance fails with "No matching credential for zone"
|
||||
- Error message: `No credential found for provider 'cloudflare' and zone 'example.com'`
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Add a catch-all credential**: Create a credential with an empty zone filter
|
||||
2. **Add specific credential**: Create a credential with zone filter matching your domain
|
||||
3. **Check zone extraction**: Ensure Charon is correctly extracting the zone from your domain
|
||||
@@ -435,10 +458,12 @@ Match Process:
|
||||
#### Issue: Wrong credential is being used
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Expected credential "Production" but "Catch-all" is being used
|
||||
- Certificate issued but not with the intended credential
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check zone filter syntax**: Verify your zone filters are correctly configured
|
||||
2. **Check priority order**: Exact matches override wildcards; ensure your exact match is configured
|
||||
3. **Review audit logs**: Check which credential was actually selected and why
|
||||
@@ -446,10 +471,12 @@ Match Process:
|
||||
#### Issue: Zone filter validation error
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Error: "Invalid zone filter format"
|
||||
- Error: "Zone filter 'example.com' conflicts with existing credential"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check syntax**: Ensure no spaces, only commas separating patterns
|
||||
2. **Check for duplicates**: Ensure no two credentials have the exact same zone filter pattern
|
||||
3. **Review wildcard syntax**: Wildcards must be `*.domain.com`, not `*domain.com`
|
||||
@@ -492,8 +519,10 @@ When you create a proxy host with multi-credential mode enabled:
|
||||
### Viewing Which Credential Was Used
|
||||
|
||||
**Method 1: Proxy Host Details**
|
||||
|
||||
1. Open the proxy host from the dashboard
|
||||
2. In the **SSL/TLS** section, look for:
|
||||
|
||||
```
|
||||
Certificate: Active (Expires: 2026-04-01)
|
||||
Credential Used: Customer A Production (Cloudflare)
|
||||
@@ -501,9 +530,11 @@ When you create a proxy host with multi-credential mode enabled:
|
||||
```
|
||||
|
||||
**Method 2: Audit Logs**
|
||||
|
||||
1. Go to **Settings** → **Audit Logs**
|
||||
2. Filter by: `Action: certificate_issued` or `Action: certificate_renewed`
|
||||
3. View log entry:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-02T14:30:00Z",
|
||||
@@ -518,6 +549,7 @@ When you create a proxy host with multi-credential mode enabled:
|
||||
```
|
||||
|
||||
**Method 3: Credential Statistics**
|
||||
|
||||
1. Go to **Settings** → **DNS Providers** → **Manage Credentials**
|
||||
2. Each credential shows:
|
||||
- **Usage Count**: Number of domains using this credential
|
||||
@@ -529,12 +561,14 @@ When you create a proxy host with multi-credential mode enabled:
|
||||
#### Issue: Certificate issuance fails with "No matching credential"
|
||||
|
||||
**Error Message:**
|
||||
|
||||
```
|
||||
Failed to issue certificate for shop.customer-a.com:
|
||||
No credential found for provider 'cloudflare' and zone 'customer-a.com'
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. Check DNS provider has multi-credential enabled
|
||||
2. Verify a credential exists with zone filter matching `customer-a.com`
|
||||
3. Add a credential with zone filter: `*.customer-a.com` or use catch-all
|
||||
@@ -542,12 +576,14 @@ No credential found for provider 'cloudflare' and zone 'customer-a.com'
|
||||
#### Issue: Certificate issuance fails with "API authentication failed"
|
||||
|
||||
**Error Message:**
|
||||
|
||||
```
|
||||
Failed to issue certificate for shop.customer-a.com:
|
||||
Cloudflare API returned 403: Invalid credentials
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. Test the credential being used: **Manage Credentials** → **Test**
|
||||
2. Verify API token/key is still valid in your DNS provider dashboard
|
||||
3. Check API token has correct permissions (`Zone:DNS:Edit`)
|
||||
@@ -556,10 +592,12 @@ Cloudflare API returned 403: Invalid credentials
|
||||
#### Issue: Wrong credential is being used
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Certificate issued successfully but with unexpected credential
|
||||
- Audit logs show different credential than expected
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. Review zone filter configuration for all credentials
|
||||
2. Check priority order (exact > wildcard > catch-all)
|
||||
3. Ensure your expected credential has the most specific zone filter
|
||||
@@ -572,6 +610,7 @@ Cloudflare API returned 403: Invalid credentials
|
||||
**Recommended Naming Patterns:**
|
||||
|
||||
**By Customer/Tenant:**
|
||||
|
||||
```
|
||||
- "Customer A - Production"
|
||||
- "Customer B - Staging"
|
||||
@@ -579,6 +618,7 @@ Cloudflare API returned 403: Invalid credentials
|
||||
```
|
||||
|
||||
**By Environment:**
|
||||
|
||||
```
|
||||
- "Production Zones"
|
||||
- "Staging Zones"
|
||||
@@ -586,6 +626,7 @@ Cloudflare API returned 403: Invalid credentials
|
||||
```
|
||||
|
||||
**By Department:**
|
||||
|
||||
```
|
||||
- "Marketing - example.com"
|
||||
- "Engineering - api.example.com"
|
||||
@@ -593,6 +634,7 @@ Cloudflare API returned 403: Invalid credentials
|
||||
```
|
||||
|
||||
**By Geography:**
|
||||
|
||||
```
|
||||
- "US East Zones"
|
||||
- "EU West Zones"
|
||||
@@ -606,6 +648,7 @@ Cloudflare API returned 403: Invalid credentials
|
||||
**Use Case:** Small number of high-value domains
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Credential: "example.com Primary"
|
||||
Zone Filter: example.com
|
||||
@@ -615,11 +658,13 @@ Zone Filter: api.example.org
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Maximum specificity
|
||||
- Easy to understand
|
||||
- Clear audit trail
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Requires one credential per domain
|
||||
- Not scalable for many domains
|
||||
|
||||
@@ -628,6 +673,7 @@ Zone Filter: api.example.org
|
||||
**Use Case:** Logical grouping of subdomains
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Credential: "Customer Zones"
|
||||
Zone Filter: *.customers.example.com
|
||||
@@ -637,11 +683,13 @@ Zone Filter: *.internal.example.com
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Scalable for many subdomains
|
||||
- Clear organizational boundaries
|
||||
- Reduces credential count
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Broader scope than exact match
|
||||
- Requires careful namespace planning
|
||||
|
||||
@@ -650,6 +698,7 @@ Zone Filter: *.internal.example.com
|
||||
**Use Case:** Most common for production deployments
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
1. Exact matches for critical domains:
|
||||
- "Production Root" → example.com
|
||||
@@ -664,11 +713,13 @@ Zone Filter: *.internal.example.com
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Balance of specificity and scalability
|
||||
- Flexible and maintainable
|
||||
- Handles edge cases
|
||||
|
||||
**Cons:**
|
||||
|
||||
- More credentials to manage
|
||||
- Requires understanding of priority order
|
||||
|
||||
@@ -718,6 +769,7 @@ Zone Filter: *.internal.example.com
|
||||
### Viewing Credential Usage Statistics
|
||||
|
||||
**Dashboard View:**
|
||||
|
||||
1. Navigate to **Settings** → **DNS Providers**
|
||||
2. For each provider with multi-credential enabled, click **View Statistics**
|
||||
3. Dashboard shows:
|
||||
@@ -727,6 +779,7 @@ Zone Filter: *.internal.example.com
|
||||
- Top credentials by usage
|
||||
|
||||
**Per-Credential View:**
|
||||
|
||||
1. Go to **Settings** → **DNS Providers** → **Manage Credentials**
|
||||
2. Each credential displays:
|
||||
|
||||
@@ -756,6 +809,7 @@ Zone Filter: *.internal.example.com
|
||||
**Success Rate**: Percentage of successful operations (Success / (Success + Failure) × 100%)
|
||||
|
||||
**⚠️ Low Success Rate Alert:**
|
||||
|
||||
- If success rate drops below 90%, investigate immediately
|
||||
- Common causes: expired API token, insufficient permissions, DNS provider API issues
|
||||
- Click **Test Credential** to diagnose
|
||||
@@ -769,6 +823,7 @@ Zone Filter: *.internal.example.com
|
||||
**Last Failure**: Timestamp of the most recent failed operation
|
||||
|
||||
**Use Cases:**
|
||||
|
||||
- **Identify Unused Credentials**: If "Last Used" is > 90 days ago, consider removing
|
||||
- **Credential Rotation**: Track when credentials were last active
|
||||
- **Incident Response**: Correlate failures with outages or credential changes
|
||||
@@ -776,6 +831,7 @@ Zone Filter: *.internal.example.com
|
||||
### Audit Trail for Credential Operations
|
||||
|
||||
**Viewing Audit Logs:**
|
||||
|
||||
1. Go to **Settings** → **Audit Logs**
|
||||
2. Filter by:
|
||||
- **Action Type**: `credential_created`, `credential_updated`, `credential_deleted`, `certificate_issued`, `certificate_renewed`
|
||||
@@ -783,6 +839,7 @@ Zone Filter: *.internal.example.com
|
||||
- **User**: Filter by who performed the action
|
||||
|
||||
**Log Entry Example:**
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-04T15:30:00Z",
|
||||
@@ -802,6 +859,7 @@ Zone Filter: *.internal.example.com
|
||||
```
|
||||
|
||||
**Exported Logs:**
|
||||
|
||||
- Export to CSV or JSON for external analysis
|
||||
- Integrate with SIEM (Security Information and Event Management) systems
|
||||
- Use for compliance reporting and security audits
|
||||
@@ -813,11 +871,13 @@ Zone Filter: *.internal.example.com
|
||||
#### Issue 1: No matching credential for domain
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Certificate issuance fails
|
||||
- Error: `No credential found for provider 'cloudflare' and zone 'example.com'`
|
||||
- Proxy host shows certificate status: "Failed"
|
||||
|
||||
**Root Causes:**
|
||||
|
||||
1. No credential configured for the DNS zone
|
||||
2. Zone filter doesn't match the domain's zone
|
||||
3. Multi-credential mode not enabled
|
||||
@@ -825,11 +885,13 @@ Zone Filter: *.internal.example.com
|
||||
**Solutions:**
|
||||
|
||||
**Step 1: Verify Multi-Credential Mode is Enabled**
|
||||
|
||||
```
|
||||
Settings → DNS Providers → Check "Multi-Credential Mode: Enabled"
|
||||
```
|
||||
|
||||
**Step 2: Check Existing Credentials**
|
||||
|
||||
```
|
||||
Settings → DNS Providers → Manage Credentials
|
||||
Review zone filters for all credentials
|
||||
@@ -838,18 +900,21 @@ Review zone filters for all credentials
|
||||
**Step 3: Add Missing Credential or Catch-All**
|
||||
|
||||
**Option A: Add Specific Credential**
|
||||
|
||||
```
|
||||
Credential Name: example.com Production
|
||||
Zone Filter: example.com
|
||||
```
|
||||
|
||||
**Option B: Add Catch-All**
|
||||
|
||||
```
|
||||
Credential Name: Catch-All
|
||||
Zone Filter: (leave empty)
|
||||
```
|
||||
|
||||
**Step 4: Retry Certificate Issuance**
|
||||
|
||||
```
|
||||
Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
```
|
||||
@@ -857,11 +922,13 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
#### Issue 2: Certificate issuance fails with API error
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Certificate issuance fails
|
||||
- Error: `Cloudflare API returned 403: Invalid credentials` or similar
|
||||
- Credential test fails
|
||||
|
||||
**Root Causes:**
|
||||
|
||||
1. API token/key expired or revoked
|
||||
2. Insufficient API permissions
|
||||
3. DNS provider account suspended
|
||||
@@ -870,30 +937,36 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
**Solutions:**
|
||||
|
||||
**Step 1: Test the Credential**
|
||||
|
||||
```
|
||||
Settings → DNS Providers → Manage Credentials → Click "Test" next to credential
|
||||
```
|
||||
|
||||
**Step 2: Check API Token Validity**
|
||||
|
||||
- Log in to your DNS provider dashboard (e.g., Cloudflare)
|
||||
- Navigate to API Tokens
|
||||
- Verify token is active and not expired
|
||||
- Check token permissions: `Zone:DNS:Edit` permission required
|
||||
|
||||
**Step 3: Regenerate API Token**
|
||||
|
||||
- Generate new API token at DNS provider
|
||||
- Update credential in Charon:
|
||||
|
||||
```
|
||||
Settings → DNS Providers → Manage Credentials → Edit → Update API credentials → Test → Save
|
||||
```
|
||||
|
||||
**Step 4: Check API Rate Limits**
|
||||
|
||||
- Review DNS provider's rate limit documentation
|
||||
- Check if you've exceeded API quotas
|
||||
- Wait for rate limit to reset (typically hourly)
|
||||
- Consider spreading certificate operations over time
|
||||
|
||||
**Step 5: Retry Certificate Issuance**
|
||||
|
||||
```
|
||||
Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
```
|
||||
@@ -901,11 +974,13 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
#### Issue 3: Zone filter validation error
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Cannot save credential
|
||||
- Error: `Invalid zone filter format: 'example..com'`
|
||||
- Error: `Zone filter 'example.com' conflicts with existing credential`
|
||||
|
||||
**Root Causes:**
|
||||
|
||||
1. Syntax error in zone filter (typo, invalid characters)
|
||||
2. Duplicate zone filter across multiple credentials
|
||||
3. Conflicting exact and wildcard patterns
|
||||
@@ -915,6 +990,7 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
**Step 1: Check Syntax**
|
||||
|
||||
**Valid Formats:**
|
||||
|
||||
```
|
||||
✅ example.com
|
||||
✅ *.customer-a.com
|
||||
@@ -924,6 +1000,7 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
```
|
||||
|
||||
**Invalid Formats:**
|
||||
|
||||
```
|
||||
❌ example..com (double dot)
|
||||
❌ example.com. (trailing dot)
|
||||
@@ -933,25 +1010,30 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
```
|
||||
|
||||
**Step 2: Check for Duplicates**
|
||||
|
||||
- Review all credentials for the provider
|
||||
- Ensure no two credentials have the exact same zone filter pattern
|
||||
- If duplicate found, edit one credential to have a different zone filter
|
||||
|
||||
**Step 3: Resolve Conflicts**
|
||||
|
||||
- If you have both `example.com` and `*.example.com`, this is allowed but may cause confusion
|
||||
- Ensure you understand priority order: exact match takes precedence
|
||||
|
||||
**Step 4: Save Again**
|
||||
|
||||
- After fixing syntax/duplicates, click **Save Credential**
|
||||
|
||||
#### Issue 4: Wrong credential is being used
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Certificate issued successfully but audit logs show unexpected credential
|
||||
- Credential statistics don't match expectations
|
||||
- Security/compliance concern about which credential was used
|
||||
|
||||
**Root Causes:**
|
||||
|
||||
1. Zone filter misconfiguration (too broad or too narrow)
|
||||
2. Misunderstanding of zone matching priority
|
||||
3. Overlapping patterns causing unexpected matches
|
||||
@@ -959,6 +1041,7 @@ Proxy Hosts → Select proxy host → SSL/TLS → Renew Certificate
|
||||
**Solutions:**
|
||||
|
||||
**Step 1: Review Zone Matching Logic**
|
||||
|
||||
```
|
||||
Priority Order:
|
||||
1. Exact match: example.com
|
||||
@@ -967,11 +1050,13 @@ Priority Order:
|
||||
```
|
||||
|
||||
**Step 2: Check Zone Extraction**
|
||||
|
||||
- For domain `shop.customer-a.com`, zone is `customer-a.com`
|
||||
- For domain `www.example.com`, zone is `example.com`
|
||||
- For domain `api.sub.example.com`, zone is `example.com` (not `sub.example.com`)
|
||||
|
||||
**Step 3: Review All Credential Zone Filters**
|
||||
|
||||
```
|
||||
Settings → DNS Providers → Manage Credentials
|
||||
List all zone filters and check for overlaps:
|
||||
@@ -986,11 +1071,13 @@ For www.example.com:
|
||||
```
|
||||
|
||||
**Step 4: Adjust Zone Filters**
|
||||
|
||||
- Make zone filters more specific to avoid unwanted matches
|
||||
- Remove or narrow catch-all if it's too broad
|
||||
- Use exact matches for critical domains
|
||||
|
||||
**Step 5: Test Zone Matching**
|
||||
|
||||
- Some Charon versions may include a zone matching test utility
|
||||
- Go to **Settings** → **DNS Providers** → **Test Zone Matching**
|
||||
- Enter a domain and see which credential would be selected
|
||||
@@ -998,11 +1085,13 @@ For www.example.com:
|
||||
#### Issue 5: Credential test succeeds but certificate issuance fails
|
||||
|
||||
**Symptoms:**
|
||||
|
||||
- Credential test passes: ✅ "Credential validated successfully"
|
||||
- Certificate issuance fails with DNS-related error
|
||||
- Error: `DNS propagation timeout` or `TXT record not found`
|
||||
|
||||
**Root Causes:**
|
||||
|
||||
1. API permissions sufficient for test but not for DNS-01 challenge
|
||||
2. DNS propagation delay
|
||||
3. Credential has access to different zones than expected
|
||||
@@ -1013,40 +1102,51 @@ For www.example.com:
|
||||
**Step 1: Check API Permissions**
|
||||
|
||||
**Cloudflare:**
|
||||
|
||||
- Required: `Zone:DNS:Edit` permission
|
||||
- Test permission alone may only check `Zone:DNS:Read`
|
||||
|
||||
**Route53:**
|
||||
|
||||
- Required: `route53:ChangeResourceRecordSets`, `route53:GetChange`
|
||||
- Test permission alone may only check `route53:ListHostedZones`
|
||||
|
||||
**Step 2: Verify Zone Access**
|
||||
|
||||
- Ensure credential has access to the specific zone
|
||||
- Check DNS provider dashboard for zone visibility
|
||||
- For Route53, ensure IAM policy includes the correct hosted zone ID
|
||||
|
||||
**Step 3: Check DNS Propagation**
|
||||
|
||||
- DNS-01 challenge requires TXT record to propagate
|
||||
- Default timeout: 60 seconds
|
||||
- Increase timeout in Charon settings if DNS provider is slow:
|
||||
|
||||
```
|
||||
Settings → Advanced → DNS Propagation Timeout: 120 seconds
|
||||
```
|
||||
|
||||
**Step 4: Manual DNS Test**
|
||||
|
||||
- After certificate issuance fails, check if TXT record was created:
|
||||
|
||||
```bash
|
||||
dig TXT _acme-challenge.shop.customer-a.com
|
||||
nslookup -type=TXT _acme-challenge.shop.customer-a.com
|
||||
```
|
||||
|
||||
- If record exists, issue is with propagation delay
|
||||
- If record doesn't exist, issue is with API permissions or credential
|
||||
|
||||
**Step 5: Review Let's Encrypt Logs**
|
||||
|
||||
- View detailed certificate issuance logs:
|
||||
|
||||
```
|
||||
Settings → Logs → Filter by: "certificate_issuance"
|
||||
```
|
||||
|
||||
- Look for specific error messages from Let's Encrypt or DNS provider
|
||||
|
||||
### Getting Help
|
||||
@@ -1072,6 +1172,7 @@ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
|
||||
```
|
||||
|
||||
**Getting an API Token:**
|
||||
|
||||
1. Go to **Settings** → **API Tokens**
|
||||
2. Click **Generate Token**
|
||||
3. Copy token (shown only once)
|
||||
@@ -1085,6 +1186,7 @@ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
|
||||
**Description:** List all credentials for a DNS provider
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X GET \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials \
|
||||
@@ -1092,6 +1194,7 @@ curl -X GET \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"credentials": [
|
||||
@@ -1133,6 +1236,7 @@ curl -X GET \
|
||||
**Description:** Get details of a specific credential
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X GET \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials/42 \
|
||||
@@ -1140,6 +1244,7 @@ curl -X GET \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 42,
|
||||
@@ -1168,6 +1273,7 @@ curl -X GET \
|
||||
**Description:** Create a new credential for a DNS provider
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials \
|
||||
@@ -1186,6 +1292,7 @@ curl -X POST \
|
||||
**Provider-Specific Credential Fields:**
|
||||
|
||||
**Cloudflare:**
|
||||
|
||||
```json
|
||||
"credentials": {
|
||||
"api_token": "your-cloudflare-api-token"
|
||||
@@ -1198,6 +1305,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Route53:**
|
||||
|
||||
```json
|
||||
"credentials": {
|
||||
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
|
||||
@@ -1206,6 +1314,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**DigitalOcean:**
|
||||
|
||||
```json
|
||||
"credentials": {
|
||||
"api_token": "your-digitalocean-api-token"
|
||||
@@ -1213,6 +1322,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 44,
|
||||
@@ -1236,6 +1346,7 @@ curl -X POST \
|
||||
**Description:** Update an existing credential
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X PATCH \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials/44 \
|
||||
@@ -1248,6 +1359,7 @@ curl -X PATCH \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 44,
|
||||
@@ -1271,6 +1383,7 @@ curl -X PATCH \
|
||||
**Description:** Delete a credential (fails if credential is in use)
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials/44 \
|
||||
@@ -1278,6 +1391,7 @@ curl -X DELETE \
|
||||
```
|
||||
|
||||
**Response (Success):**
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Credential deleted successfully",
|
||||
@@ -1286,6 +1400,7 @@ curl -X DELETE \
|
||||
```
|
||||
|
||||
**Response (Error - In Use):**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Cannot delete credential: 3 proxy hosts are using this credential",
|
||||
@@ -1304,6 +1419,7 @@ curl -X DELETE \
|
||||
**Description:** Test if a credential is valid and has correct permissions
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/credentials/42/test \
|
||||
@@ -1311,6 +1427,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Response (Success):**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
@@ -1326,6 +1443,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Response (Failure):**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "failed",
|
||||
@@ -1345,6 +1463,7 @@ curl -X POST \
|
||||
**Description:** Enable multi-credential mode for a DNS provider
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/enable-multi-credential \
|
||||
@@ -1352,6 +1471,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Multi-credential mode enabled",
|
||||
@@ -1372,6 +1492,7 @@ curl -X POST \
|
||||
**Description:** Disable multi-credential mode (reverts to first credential as primary)
|
||||
|
||||
**Request:**
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
https://your-charon-instance/api/v1/dns-providers/1/disable-multi-credential \
|
||||
@@ -1379,6 +1500,7 @@ curl -X POST \
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Multi-credential mode disabled",
|
||||
@@ -1396,6 +1518,7 @@ curl -X POST \
|
||||
All API endpoints may return the following error responses:
|
||||
|
||||
**400 Bad Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Invalid zone filter format",
|
||||
@@ -1404,6 +1527,7 @@ All API endpoints may return the following error responses:
|
||||
```
|
||||
|
||||
**401 Unauthorized:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Unauthorized",
|
||||
@@ -1412,6 +1536,7 @@ All API endpoints may return the following error responses:
|
||||
```
|
||||
|
||||
**403 Forbidden:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Forbidden",
|
||||
@@ -1420,6 +1545,7 @@ All API endpoints may return the following error responses:
|
||||
```
|
||||
|
||||
**404 Not Found:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Not found",
|
||||
@@ -1428,6 +1554,7 @@ All API endpoints may return the following error responses:
|
||||
```
|
||||
|
||||
**409 Conflict:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Conflict",
|
||||
@@ -1437,6 +1564,7 @@ All API endpoints may return the following error responses:
|
||||
```
|
||||
|
||||
**500 Internal Server Error:**
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Internal server error",
|
||||
@@ -1484,5 +1612,5 @@ All API endpoints may return the following error responses:
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: January 4, 2026*
|
||||
*Version: 1.3.0*
|
||||
_Last Updated: January 4, 2026_
|
||||
_Version: 1.3.0_
|
||||
|
||||
@@ -56,6 +56,7 @@ Simple, clean notifications with essential information:
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
|
||||
- You want low-noise notifications
|
||||
- Space is limited (mobile notifications)
|
||||
- Only essential info is needed
|
||||
@@ -80,6 +81,7 @@ Comprehensive notifications with all available context:
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
|
||||
- You need full event context
|
||||
- Multiple team members review notifications
|
||||
- Historical tracking is important
|
||||
@@ -89,6 +91,7 @@ Comprehensive notifications with all available context:
|
||||
Create your own template with complete control over structure and formatting.
|
||||
|
||||
**Use when:**
|
||||
|
||||
- Standard templates don't meet your needs
|
||||
- You have specific formatting requirements
|
||||
- Integrating with custom systems
|
||||
@@ -348,6 +351,7 @@ Some events include additional variables:
|
||||
If you've been using webhook providers without JSON templates:
|
||||
|
||||
**Before (Basic webhook):**
|
||||
|
||||
```
|
||||
Type: webhook
|
||||
URL: https://discord.com/api/webhooks/...
|
||||
@@ -355,6 +359,7 @@ Template: (not available)
|
||||
```
|
||||
|
||||
**After (JSON template):**
|
||||
|
||||
```
|
||||
Type: discord
|
||||
URL: https://discord.com/api/webhooks/...
|
||||
@@ -386,6 +391,7 @@ Before saving, always test your template:
|
||||
**Error:** `Invalid JSON template`
|
||||
|
||||
**Solution:** Validate your JSON using a tool like [jsonlint.com](https://jsonlint.com). Common issues:
|
||||
|
||||
- Missing closing braces `}`
|
||||
- Trailing commas
|
||||
- Unescaped quotes in strings
|
||||
@@ -455,6 +461,7 @@ Always test notifications before relying on them for critical alerts.
|
||||
### 3. Use Color Coding
|
||||
|
||||
Consistent colors help quickly identify severity:
|
||||
|
||||
- 🔴 Red: Errors, outages
|
||||
- 🟡 Yellow: Warnings
|
||||
- 🟢 Green: Success, recovery
|
||||
@@ -463,6 +470,7 @@ Consistent colors help quickly identify severity:
|
||||
### 4. Group Related Events
|
||||
|
||||
Configure multiple providers for different event types:
|
||||
|
||||
- Critical alerts → Discord (with mentions)
|
||||
- Info notifications → Slack (general channel)
|
||||
- All events → Gotify (personal alerts)
|
||||
@@ -470,6 +478,7 @@ Configure multiple providers for different event types:
|
||||
### 5. Rate Limit Awareness
|
||||
|
||||
Be mindful of service limits:
|
||||
|
||||
- **Discord**: 5 requests per 2 seconds per webhook
|
||||
- **Slack**: 1 request per second per workspace
|
||||
- **Gotify**: No strict limits (self-hosted)
|
||||
|
||||
@@ -56,12 +56,14 @@ Check 4: ✅ Success → Status: Up, Failure Count: 0 (recovery alert)
|
||||
This timeout determines how long Charon waits for a TCP connection before considering it failed.
|
||||
|
||||
**Increase timeout if:**
|
||||
|
||||
- You have slow networks
|
||||
- Hosts are geographically distant
|
||||
- Containers take time to warm up
|
||||
- You see intermittent false "down" alerts
|
||||
|
||||
**Decrease timeout if:**
|
||||
|
||||
- You want faster failure detection
|
||||
- Your hosts are on local network
|
||||
- Response times are consistently fast
|
||||
|
||||
Reference in New Issue
Block a user