# Audit Logging Charon's audit logging system provides comprehensive tracking of all DNS provider credential operations, giving you complete visibility into who accessed, modified, or used sensitive credentials. ## Overview Audit logging automatically records security-sensitive operations for compliance, security monitoring, and troubleshooting. Every action involving DNS provider credentials is tracked with full context including: - **Who**: User ID or system actor - **What**: Specific action performed (create, update, delete, test, decrypt) - **When**: Precise timestamp - **Where**: IP address and user agent - **Why**: Full event context and metadata ### Why Audit Logging Matters - **Security Monitoring**: Detect unauthorized access or suspicious patterns - **Compliance**: Meet SOC 2, GDPR, HIPAA, and PCI-DSS requirements for audit trails - **Troubleshooting**: Diagnose certificate issuance failures retrospectively - **Accountability**: Track all credential operations with full attribution ## Accessing Audit Logs ### Navigation 1. Navigate to **Security** in the main menu 2. Click **Audit Logs** in the submenu 3. The audit log table displays recent events with pagination ### UI Overview The audit log interface consists of: - **Data Table**: Lists all audit events with key information - **Filter Bar**: Refine results by date, category, actor, action, or resource - **Search Box**: Full-text search across event details - **Details Modal**: View complete event information with related events - **Export Button**: Download audit logs as CSV for external analysis ## Understanding Audit Events ### Event Categories All audit events are categorized for easy filtering: | Category | Description | Example Events | |----------|-------------|----------------| | `dns_provider` | DNS provider credential operations | Create, update, delete, test credentials | | `certificate` | Certificate lifecycle events | Issuance, renewal, failure | | `system` | System-level operations | Automated credential decryption | ### Event Actions Charon logs the following DNS provider operations: | Action | When It's Logged | Details Captured | |--------|------------------|------------------| | `dns_provider_create` | New DNS provider added | Provider name, type, is_default flag | | `dns_provider_update` | Provider settings changed | Changed fields, old values, new values | | `dns_provider_delete` | Provider removed | Provider name, type, whether credentials existed | | `credential_test` | Credentials tested via API | Provider name, test result, error message | | `credential_decrypt` | Caddy reads credentials for cert issuance | Provider name, purpose (certificate_issuance) | | `certificate_issued` | Certificate successfully issued | Domain, provider used, success/failure status | ## Filtering and Search ### Date Range Filter Filter events by time period: 1. Click the **Date Range** dropdown 2. Select a preset (**Last 24 Hours**, **Last 7 Days**, **Last 30 Days**, **Last 90 Days**) 3. Or select **Custom Range** and pick specific start and end dates 4. Results update automatically ### Category Filter Filter by event category: 1. Click the **Category** dropdown 2. Select one or more categories (dns_provider, certificate, system) 3. Only events matching selected categories will be displayed ### Actor Filter Filter by who performed the action: 1. Click the **Actor** dropdown 2. Select a user from the list (shows both username and user ID) 3. Select **System** to see automated operations 4. View only events from the selected actor ### Action Filter Filter by specific operation type: 1. Click the **Action** dropdown 2. Select one or more actions (create, update, delete, test, decrypt) 3. Results show only the selected action types ### Resource Filter Filter by specific DNS provider: 1. Click the **Resource** dropdown 2. Select a DNS provider from the list 3. View only events related to that provider ### Search Perform free-text search across all event details: 1. Enter search terms in the **Search** box 2. Press Enter or click the search icon 3. Results include events where the search term appears in: - Provider name - Event details JSON - IP addresses - User agents ### Clearing Filters - Click the **Clear Filters** button to reset all filters - Filters persist while navigating within the audit log page - Filters reset when you leave and return to the page ## Viewing Event Details ### Opening the Details Modal 1. Click any row in the audit log table 2. Or click the **View Details** button on the right side of a row ### Details Modal Contents The details modal displays: - **Event UUID**: Unique identifier for the event - **Timestamp**: Exact date and time (ISO 8601 format) - **Actor**: User ID or "system" for automated operations - **Action**: Operation performed - **Category**: Event category (dns_provider, certificate, etc.) - **Resource**: DNS provider name and UUID - **IP Address**: Client IP that initiated the operation - **User Agent**: Browser or API client information - **Full Details**: Complete JSON payload with all event metadata ### Understanding the Details JSON The details field contains a JSON object with event-specific information: **Create Event Example:** ```json { "name": "Cloudflare Production", "type": "cloudflare", "is_default": true } ``` **Update Event Example:** ```json { "changed_fields": ["credentials", "is_default"], "old_values": { "is_default": false }, "new_values": { "is_default": true } } ``` **Test Event Example:** ```json { "test_result": "success", "response_time_ms": 342 } ``` **Decrypt Event Example:** ```json { "purpose": "certificate_issuance", "success": true } ``` ### Finding Related Events 1. In the details modal, note the **Resource UUID** 2. Click **View Related Events** to see all events for this resource 3. Or manually filter by Resource UUID using the filter bar ## Exporting Audit Logs ### CSV Export Export audit logs for external analysis, compliance reporting, or archival: 1. Apply desired filters to narrow down events 2. Click the **Export CSV** button 3. A CSV file downloads with the following columns: - Timestamp - Actor - Action - Event Category - Resource ID - Resource UUID - IP Address - User Agent - Details ### Export Use Cases - **Compliance Reports**: Generate quarterly audit reports for SOC 2 - **Security Analysis**: Import into SIEM tools for threat detection - **Forensics**: Investigate security incidents with complete audit trail - **Backup**: Archive audit logs beyond the retention period ### Export Limitations - Exports are limited to 10,000 events per download - For larger exports, use date range filters to split into multiple files - Exports respect all active filters (date, category, actor, etc.) ## Event Scenarios ### 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} ``` ### 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} ``` ### 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"} ``` ### 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}} ``` ### 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} ``` ## Viewing Provider-Specific Audit History ### From DNS Provider Page 1. Navigate to **Settings** → **DNS Providers** 2. Click on any DNS provider to open the edit form 3. Click the **View Audit History** button 4. See all audit events for this specific provider ### API Endpoint You can also retrieve provider-specific audit logs via API: ```bash GET /api/v1/dns-providers/:id/audit-logs?page=1&limit=50 ``` ## Troubleshooting ### Common Questions **Q: Why don't I see audit logs from before today?** A: Audit logging was introduced in Charon v1.2.0. Only events after the feature was enabled are logged. Previous operations are not retroactively logged. **Q: How long are audit logs kept?** A: By default, audit logs are retained for 90 days. After 90 days, logs are automatically deleted to prevent unbounded database growth. Administrators can configure the retention period via environment variable `AUDIT_LOG_RETENTION_DAYS`. **Q: Can audit logs be modified or deleted?** A: No. Audit logs are immutable and append-only. Only the automatic cleanup job (based on retention policy) can delete logs. This ensures audit trail integrity for compliance purposes. **Q: What happens if audit logging fails?** A: Audit logging is non-blocking and asynchronous. If the audit log channel is full or the database is temporarily unavailable, the event is dropped but the primary operation (e.g., creating a DNS provider) succeeds. Dropped events are logged to the application log for monitoring. **Q: Do audit logs include credential values?** A: No. Audit logs never include actual credential values (API keys, tokens, passwords). Only metadata about the operation is logged (provider name, type, whether credentials were present). **Q: Can I see who viewed credentials?** A: Credentials are never "viewed" directly. The only access logged is when credentials are decrypted for certificate issuance (logged as `credential_decrypt` with actor "system"). ### Performance Impact Audit logging is designed for minimal performance impact: - **Asynchronous Writes**: Audit events are written via a buffered channel and background goroutine - **Non-Blocking**: Failed audit writes do not block API operations - **Indexed Queries**: Database indexes on `created_at`, `event_category`, `resource_uuid`, and `actor` ensure fast filtering - **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 ### Missing Events If you expect to see an event but don't: 1. **Check filters**: Clear all filters and search to see all events 2. **Check date range**: Expand date range to "Last 90 Days" 3. **Check retention policy**: Event may have been automatically deleted 4. **Check application logs**: Look for "audit channel full" or "Failed to write audit log" messages ### Slow Query Performance If audit log pages load slowly: 1. **Narrow date range**: Searching 90 days of logs is slower than 7 days 2. **Use specific filters**: Filter by category, actor, or action before searching 3. **Check database indexes**: Ensure indexes on `security_audits` table are present 4. **Consider archival**: Export and delete old logs if database is very large ## API Reference ### List Audit Logs 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") - `action` (string): Filter by action type - `event_category` (string): Filter by category (dns_provider, certificate, etc.) - `resource_uuid` (string): Filter by resource UUID - `start_date` (RFC3339): Start of date range - `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": [ { "id": 1, "uuid": "550e8400-e29b-41d4-a716-446655440000", "actor": "user:5", "action": "dns_provider_create", "event_category": "dns_provider", "resource_id": 3, "resource_uuid": "660e8400-e29b-41d4-a716-446655440001", "details": "{\"name\":\"Cloudflare\",\"type\":\"cloudflare\",\"is_default\":true}", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0", "created_at": "2026-01-03T14:23:45Z" } ], "pagination": { "page": 1, "limit": 50, "total": 1, "total_pages": 1 } } ``` ### Get Single Audit 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, "uuid": "550e8400-e29b-41d4-a716-446655440000", "actor": "user:5", "action": "dns_provider_create", "event_category": "dns_provider", "resource_id": 3, "resource_uuid": "660e8400-e29b-41d4-a716-446655440001", "details": "{\"name\":\"Cloudflare\",\"type\":\"cloudflare\",\"is_default\":true}", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0", "created_at": "2026-01-03T14:23:45Z" } ``` ### Get Provider Audit History 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": [ { "id": 3, "uuid": "770e8400-e29b-41d4-a716-446655440002", "actor": "user:5", "action": "dns_provider_update", "event_category": "dns_provider", "resource_id": 3, "resource_uuid": "660e8400-e29b-41d4-a716-446655440001", "details": "{\"changed_fields\":[\"is_default\"],\"new_values\":{\"is_default\":true}}", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0", "created_at": "2026-01-03T15:00:22Z" }, { "id": 1, "uuid": "550e8400-e29b-41d4-a716-446655440000", "actor": "user:5", "action": "dns_provider_create", "event_category": "dns_provider", "resource_id": 3, "resource_uuid": "660e8400-e29b-41d4-a716-446655440001", "details": "{\"name\":\"Cloudflare\",\"type\":\"cloudflare\",\"is_default\":true}", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0", "created_at": "2026-01-03T14:23:45Z" } ], "pagination": { "page": 1, "limit": 50, "total": 2, "total_pages": 1 } } ``` ### Authentication All audit log API endpoints require authentication. Include a valid session cookie or Bearer token: ```bash # Cookie-based auth (from browser) Cookie: session=YOUR_SESSION_TOKEN # Bearer token auth (from API client) Authorization: Bearer YOUR_API_TOKEN ``` ### Error Responses | Status Code | Error | Description | |-------------|-------|-------------| | 400 | Invalid parameter | Invalid page/limit or malformed date | | 401 | Unauthorized | Missing or invalid authentication | | 404 | Not found | Audit event UUID does not exist | | 500 | Server error | Database error or service unavailable | ## Configuration ### Retention Period 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: environment: - AUDIT_LOG_RETENTION_DAYS=180 # 6 months ``` ### Channel Buffer Size Configure the size of the audit log channel buffer (advanced): **Environment Variable:** ```bash AUDIT_LOG_CHANNEL_SIZE=1000 # Default: 1000 events ``` Increase if you see "audit channel full" errors in application logs during high-load periods. ## Best Practices 1. **Regular Reviews**: Schedule weekly or monthly reviews of audit logs to spot anomalies 2. **Alert on Patterns**: Set up alerts for suspicious patterns (e.g., bulk deletions, off-hours access) 3. **Export for Compliance**: Regularly export logs for compliance archival before they're auto-deleted 4. **Filter Before Export**: Use filters to export only relevant events for specific audits 5. **Document Procedures**: Create runbooks for investigating common security scenarios 6. **Integrate with SIEM**: Export logs to your SIEM tool for centralized security monitoring 7. **Test Retention Policy**: Verify the retention period meets your compliance requirements ## Security Considerations - **Immutable Logs**: Audit logs cannot be modified or deleted by users (only auto-cleanup) - **No Credential Leakage**: Actual credential values are never logged - **Complete Attribution**: Every event includes actor, IP, and user agent for full traceability - **Secure Storage**: Audit logs are stored in the same encrypted database as other sensitive data - **Access Control**: Audit log viewing requires authentication (no anonymous access) ## Related Features - [DNS Challenge Support](./dns-challenge.md) - Configure DNS providers for automated certificates - [Security Features](./security.md) - WAF, access control, and security notifications - [Notifications](./notifications.md) - Get alerts for security events ## Support For questions or issues with audit logging: 1. Check the [Troubleshooting](#troubleshooting) section above 2. Review the [GitHub Issues](https://github.com/Wikid82/charon/issues) for known problems 3. Open a new issue with the `audit-logging` label 4. Join the [Discord community](https://discord.gg/charon) for real-time support --- **Last Updated:** January 3, 2026 **Feature Version:** v1.2.0 **Documentation Version:** 1.0