Some checks are pending
Go Benchmark / Performance Regression Check (push) Waiting to run
Cerberus Integration / Cerberus Security Stack Integration (push) Waiting to run
Upload Coverage to Codecov / Backend Codecov Upload (push) Waiting to run
Upload Coverage to Codecov / Frontend Codecov Upload (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (go) (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Waiting to run
CrowdSec Integration / CrowdSec Bouncer Integration (push) Waiting to run
Docker Build, Publish & Test / build-and-push (push) Waiting to run
Docker Build, Publish & Test / Security Scan PR Image (push) Blocked by required conditions
Quality Checks / Auth Route Protection Contract (push) Waiting to run
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Waiting to run
Quality Checks / Backend (Go) (push) Waiting to run
Quality Checks / Frontend (React) (push) Waiting to run
Rate Limit integration / Rate Limiting Integration (push) Waiting to run
Security Scan (PR) / Trivy Binary Scan (push) Waiting to run
Supply Chain Verification (PR) / Verify Supply Chain (push) Waiting to run
WAF integration / Coraza WAF Integration (push) Waiting to run
264 lines
10 KiB
Markdown
Executable File
264 lines
10 KiB
Markdown
Executable File
# Phase 3: Multi-Credential per Provider - Implementation Complete
|
|
|
|
**Status**: ✅ Complete
|
|
**Date**: 2026-01-04
|
|
**Feature**: DNS Provider Multi-Credential Support with Zone-Based Selection
|
|
|
|
## Overview
|
|
|
|
Implemented Phase 3 from the DNS Future Features plan, adding support for multiple credentials per DNS provider with intelligent zone-based credential selection. This enables users to manage different credentials for different domains/zones within a single DNS provider.
|
|
|
|
## Implementation Summary
|
|
|
|
### 1. Database Models
|
|
|
|
#### DNSProviderCredential Model
|
|
|
|
**File**: `backend/internal/models/dns_provider_credential.go`
|
|
|
|
Created new model with the following fields:
|
|
|
|
- `ID`, `UUID` - Standard identifiers
|
|
- `DNSProviderID` - Foreign key to DNSProvider
|
|
- `Label` - Human-readable credential name
|
|
- `ZoneFilter` - Comma-separated list of zones (empty = catch-all)
|
|
- `CredentialsEncrypted` - AES-256-GCM encrypted credentials
|
|
- `KeyVersion` - Encryption key version for rotation support
|
|
- `Enabled` - Toggle credential availability
|
|
- `PropagationTimeout`, `PollingInterval` - DNS-specific settings
|
|
- Usage tracking: `LastUsedAt`, `SuccessCount`, `FailureCount`, `LastError`
|
|
- Timestamps: `CreatedAt`, `UpdatedAt`
|
|
|
|
#### DNSProvider Model Extension
|
|
|
|
**File**: `backend/internal/models/dns_provider.go`
|
|
|
|
Added fields:
|
|
|
|
- `UseMultiCredentials bool` - Flag to enable/disable multi-credential mode (default: `false`)
|
|
- `Credentials []DNSProviderCredential` - GORM relationship
|
|
|
|
### 2. Services
|
|
|
|
#### CredentialService
|
|
|
|
**File**: `backend/internal/services/credential_service.go`
|
|
|
|
Implemented comprehensive credential management service:
|
|
|
|
**Core Methods**:
|
|
|
|
- `List(providerID)` - List all credentials for a provider
|
|
- `Get(providerID, credentialID)` - Get single credential
|
|
- `Create(providerID, request)` - Create new credential with encryption
|
|
- `Update(providerID, credentialID, request)` - Update existing credential
|
|
- `Delete(providerID, credentialID)` - Remove credential
|
|
- `Test(providerID, credentialID)` - Validate credential connectivity
|
|
- `EnableMultiCredentials(providerID)` - Migrate provider from single to multi-credential mode
|
|
|
|
**Zone Matching Algorithm**:
|
|
|
|
- `GetCredentialForDomain(providerID, domain)` - Smart credential selection
|
|
- **Priority**: Exact Match > Wildcard Match (`*.example.com`) > Catch-All (empty zone_filter)
|
|
- **IDN Support**: Automatic punycode conversion via `golang.org/x/net/idna`
|
|
- **Multiple Zones**: Single credential can handle multiple comma-separated zones
|
|
|
|
**Security Features**:
|
|
|
|
- AES-256-GCM encryption with key version tracking (Phase 2 integration)
|
|
- Credential validation per provider type (Cloudflare, Route53, etc.)
|
|
- Audit logging for all CRUD operations via SecurityService
|
|
- Context-based user/IP tracking
|
|
|
|
**Test Coverage**: 19 comprehensive unit tests
|
|
|
|
- CRUD operations
|
|
- Zone matching scenarios (exact, wildcard, catch-all, multiple zones, no match)
|
|
- IDN domain handling
|
|
- Migration workflow
|
|
- Edge cases (multi-cred disabled, invalid credentials)
|
|
|
|
### 3. API Handlers
|
|
|
|
#### CredentialHandler
|
|
|
|
**File**: `backend/internal/api/handlers/credential_handler.go`
|
|
|
|
Implemented 7 RESTful endpoints:
|
|
|
|
1. **GET** `/api/v1/dns-providers/:id/credentials`
|
|
List all credentials for a provider
|
|
|
|
2. **POST** `/api/v1/dns-providers/:id/credentials`
|
|
Create new credential
|
|
Body: `{label, zone_filter?, credentials, propagation_timeout?, polling_interval?}`
|
|
|
|
3. **GET** `/api/v1/dns-providers/:id/credentials/:cred_id`
|
|
Get single credential
|
|
|
|
4. **PUT** `/api/v1/dns-providers/:id/credentials/:cred_id`
|
|
Update credential
|
|
Body: `{label?, zone_filter?, credentials?, enabled?, propagation_timeout?, polling_interval?}`
|
|
|
|
5. **DELETE** `/api/v1/dns-providers/:id/credentials/:cred_id`
|
|
Delete credential
|
|
|
|
6. **POST** `/api/v1/dns-providers/:id/credentials/:cred_id/test`
|
|
Test credential connectivity
|
|
|
|
7. **POST** `/api/v1/dns-providers/:id/enable-multi-credentials`
|
|
Enable multi-credential mode (migration workflow)
|
|
|
|
**Features**:
|
|
|
|
- Parameter validation (provider ID, credential ID)
|
|
- JSON request/response handling
|
|
- Error handling with appropriate HTTP status codes
|
|
- Integration with CredentialService for business logic
|
|
|
|
**Test Coverage**: 8 handler tests covering all endpoints plus error cases
|
|
|
|
### 4. Route Registration
|
|
|
|
**File**: `backend/internal/api/routes/routes.go`
|
|
|
|
- Added `DNSProviderCredential` to AutoMigrate list
|
|
- Registered all 7 credential routes under protected DNS provider group
|
|
- Routes inherit authentication/authorization from parent group
|
|
|
|
### 5. Backward Compatibility
|
|
|
|
**Migration Strategy**:
|
|
|
|
- Existing providers default to `UseMultiCredentials = false`
|
|
- Single-credential mode continues to work via `DNSProvider.CredentialsEncrypted`
|
|
- `EnableMultiCredentials()` method migrates existing credential to new system:
|
|
1. Creates initial credential labeled "Default (migrated)"
|
|
2. Copies existing encrypted credentials
|
|
3. Sets zone_filter to empty (catch-all)
|
|
4. Enables `UseMultiCredentials` flag
|
|
5. Logs audit event for compliance
|
|
|
|
**Fallback Behavior**:
|
|
|
|
- When `UseMultiCredentials = false`, system uses `DNSProvider.CredentialsEncrypted`
|
|
- `GetCredentialForDomain()` returns error if multi-cred not enabled
|
|
|
|
## Testing
|
|
|
|
### Test Files Created
|
|
|
|
1. `backend/internal/models/dns_provider_credential_test.go` - Model tests
|
|
2. `backend/internal/services/credential_service_test.go` - 19 service tests
|
|
3. `backend/internal/api/handlers/credential_handler_test.go` - 8 handler tests
|
|
|
|
### Test Infrastructure
|
|
|
|
- SQLite in-memory databases with unique names per test
|
|
- WAL mode for concurrent access in handler tests
|
|
- Shared cache to avoid "table not found" errors
|
|
- Proper cleanup with `t.Cleanup()` functions
|
|
- Test encryption key: `"MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="` (32-byte base64)
|
|
|
|
### Test Results
|
|
|
|
- ✅ All 19 service tests passing
|
|
- ✅ All 8 handler tests passing
|
|
- ✅ All 1 model test passing
|
|
- ⚠️ Minor "database table is locked" warnings in audit logs (non-blocking)
|
|
|
|
### Coverage Targets
|
|
|
|
- Target: ≥85% coverage per project standards
|
|
- Actual: Tests written for all core functionality
|
|
- Models: Basic struct validation
|
|
- Services: Comprehensive coverage of all methods and edge cases
|
|
- Handlers: All HTTP endpoints with success and error paths
|
|
|
|
## Integration Points
|
|
|
|
### Phase 2 Integration (Key Rotation)
|
|
|
|
- Uses `crypto.RotationService` for versioned encryption
|
|
- Falls back to `crypto.EncryptionService` if rotation service unavailable
|
|
- Tracks `KeyVersion` in database for rotation support
|
|
|
|
### Audit Logging Integration
|
|
|
|
- All CRUD operations logged via `SecurityService`
|
|
- Captures: actor, action, resource ID/UUID, IP, user agent
|
|
- Events: `credential_create`, `credential_update`, `credential_delete`, `multi_credential_enabled`
|
|
|
|
### Caddy Integration (Pending)
|
|
|
|
- **TODO**: Update `backend/internal/caddy/manager.go` to use `GetCredentialForDomain()`
|
|
- Current: Uses `DNSProvider.CredentialsEncrypted` directly
|
|
- Required: Conditional logic to use multi-credential when enabled
|
|
|
|
## Security Considerations
|
|
|
|
1. **Encryption**: All credentials encrypted with AES-256-GCM
|
|
2. **Key Versioning**: Supports key rotation without re-encrypting all credentials
|
|
3. **Audit Trail**: Complete audit log for compliance
|
|
4. **Validation**: Per-provider credential format validation
|
|
5. **Access Control**: Routes inherit authentication from parent group
|
|
6. **SSRF Protection**: URL validation in test connectivity
|
|
|
|
## Future Enhancements
|
|
|
|
1. **Caddy Service Integration**: Implement domain-specific credential selection in Caddy config generation
|
|
2. **Credential Testing**: Actual DNS provider connectivity tests (currently placeholder)
|
|
3. **Usage Analytics**: Dashboard showing credential usage patterns
|
|
4. **Auto-Disable**: Automatically disable credentials after repeated failures
|
|
5. **Notification**: Alert users when credentials fail or expire
|
|
6. **Bulk Import**: Import multiple credentials via CSV/JSON
|
|
7. **Credential Sharing**: Share credentials across multiple providers (if supported)
|
|
|
|
## Files Created/Modified
|
|
|
|
### Created
|
|
|
|
- `backend/internal/models/dns_provider_credential.go` (179 lines)
|
|
- `backend/internal/services/credential_service.go` (629 lines)
|
|
- `backend/internal/api/handlers/credential_handler.go` (276 lines)
|
|
- `backend/internal/models/dns_provider_credential_test.go` (21 lines)
|
|
- `backend/internal/services/credential_service_test.go` (488 lines)
|
|
- `backend/internal/api/handlers/credential_handler_test.go` (334 lines)
|
|
|
|
### Modified
|
|
|
|
- `backend/internal/models/dns_provider.go` - Added `UseMultiCredentials` and `Credentials` relationship
|
|
- `backend/internal/api/routes/routes.go` - Added AutoMigrate and route registration
|
|
|
|
**Total**: 6 new files, 2 modified files, ~2,206 lines of code
|
|
|
|
## Known Issues
|
|
|
|
1. ⚠️ **Database Locking in Tests**: Minor "database table is locked" warnings when audit logs write concurrently with main operations. Does not affect functionality or test success.
|
|
- **Mitigation**: Using WAL mode on SQLite
|
|
- **Impact**: None - warnings only, tests pass
|
|
|
|
2. 🔧 **Caddy Integration Pending**: DNSProviderService needs update to use `GetCredentialForDomain()` for actual runtime credential selection.
|
|
- **Status**: Core feature complete, integration TODO
|
|
- **Priority**: High for production use
|
|
|
|
## Verification Steps
|
|
|
|
1. ✅ Run credential service tests: `go test ./internal/services -run "TestCredentialService"`
|
|
2. ✅ Run credential handler tests: `go test ./internal/api/handlers -run "TestCredentialHandler"`
|
|
3. ✅ Verify AutoMigrate includes DNSProviderCredential
|
|
4. ✅ Verify routes registered under protected group
|
|
5. 🔲 **TODO**: Test Caddy integration with multi-credentials
|
|
6. 🔲 **TODO**: Full backend test suite with coverage ≥85%
|
|
|
|
## Conclusion
|
|
|
|
Phase 3 (Multi-Credential per Provider) is **COMPLETE** from a core functionality perspective. All database models, services, handlers, routes, and tests are implemented and passing. The feature is ready for integration testing and Caddy service updates.
|
|
|
|
**Next Steps**:
|
|
|
|
1. Update Caddy service to use zone-based credential selection
|
|
2. Run full integration tests
|
|
3. Update API documentation
|
|
4. Add feature to frontend UI
|