feat: add nightly branch workflow
This commit is contained in:
@@ -30,6 +30,7 @@ type DNSProviderConfig struct {
|
||||
**File:** `backend/internal/caddy/manager.go` (Lines 51-58)
|
||||
|
||||
Created interface for improved testability:
|
||||
|
||||
```go
|
||||
type CaddyClient interface {
|
||||
Load(context.Context, io.Reader, bool) error
|
||||
@@ -43,6 +44,7 @@ type CaddyClient interface {
|
||||
**File:** `backend/internal/caddy/manager.go` (Lines 100-118)
|
||||
|
||||
Modified provider detection loop to properly handle multi-credential providers:
|
||||
|
||||
- Detects `UseMultiCredentials=true` flag
|
||||
- Adds providers with empty Credentials field for Phase 2 processing
|
||||
- Maintains backward compatibility for single-credential providers
|
||||
@@ -52,6 +54,7 @@ Modified provider detection loop to properly handle multi-credential providers:
|
||||
**File:** `backend/internal/caddy/manager.go` (Lines 147-213)
|
||||
|
||||
Implemented comprehensive credential resolution logic:
|
||||
|
||||
- Iterates through all proxy hosts
|
||||
- Calls `getCredentialForDomain` helper for each domain
|
||||
- Builds `ZoneCredentials` map per provider
|
||||
@@ -59,6 +62,7 @@ Implemented comprehensive credential resolution logic:
|
||||
- Error handling for missing credentials
|
||||
|
||||
**Key Code Segment:**
|
||||
|
||||
```go
|
||||
// Phase 2: For multi-credential providers, resolve per-domain credentials
|
||||
for _, providerConf := range dnsProviderConfigs {
|
||||
@@ -86,17 +90,20 @@ for _, providerConf := range dnsProviderConfigs {
|
||||
Enhanced `buildDNSChallengeIssuer` with conditional branching:
|
||||
|
||||
**Multi-Credential Path (Lines 184-254):**
|
||||
|
||||
- Creates separate TLS automation policies per domain
|
||||
- Matches domains to base domains for proper credential mapping
|
||||
- Builds per-domain provider configurations
|
||||
- Supports exact match, wildcard, and catch-all zones
|
||||
|
||||
**Single-Credential Path (Lines 256-280):**
|
||||
|
||||
- Preserved original logic for backward compatibility
|
||||
- Single policy for all domains
|
||||
- Uses shared credentials
|
||||
|
||||
**Key Decision Logic:**
|
||||
|
||||
```go
|
||||
if providerConf.UseMultiCredentials {
|
||||
// Multi-credential: Create separate policy per domain
|
||||
@@ -123,12 +130,14 @@ if providerConf.UseMultiCredentials {
|
||||
Implemented 4 comprehensive integration test scenarios:
|
||||
|
||||
#### Test 1: Single-Credential Backward Compatibility
|
||||
|
||||
- **Purpose:** Verify existing single-credential providers work unchanged
|
||||
- **Setup:** Standard DNSProvider with `UseMultiCredentials=false`
|
||||
- **Validation:** Single TLS policy created with shared credentials
|
||||
- **Result:** ✅ PASS
|
||||
|
||||
#### Test 2: Multi-Credential Exact Match
|
||||
|
||||
- **Purpose:** Test exact zone filter matching (example.com, example.org)
|
||||
- **Setup:**
|
||||
- Provider with `UseMultiCredentials=true`
|
||||
@@ -140,6 +149,7 @@ Implemented 4 comprehensive integration test scenarios:
|
||||
- **Result:** ✅ PASS
|
||||
|
||||
#### Test 3: Multi-Credential Wildcard Match
|
||||
|
||||
- **Purpose:** Test wildcard zone filter matching (*.example.com)
|
||||
- **Setup:**
|
||||
- Credential with `*.example.com` zone filter
|
||||
@@ -148,6 +158,7 @@ Implemented 4 comprehensive integration test scenarios:
|
||||
- **Result:** ✅ PASS
|
||||
|
||||
#### Test 4: Multi-Credential Catch-All
|
||||
|
||||
- **Purpose:** Test empty zone filter (catch-all) matching
|
||||
- **Setup:**
|
||||
- Credential with empty zone_filter
|
||||
@@ -156,6 +167,7 @@ Implemented 4 comprehensive integration test scenarios:
|
||||
- **Result:** ✅ PASS
|
||||
|
||||
**Helper Functions:**
|
||||
|
||||
- `encryptCredentials()`: AES-256-GCM encryption with proper base64 encoding
|
||||
- `setupTestDB()`: Creates in-memory SQLite with all required tables
|
||||
- `assertDNSChallengeCredential()`: Validates TLS policy credentials
|
||||
@@ -164,6 +176,7 @@ Implemented 4 comprehensive integration test scenarios:
|
||||
## Test Results
|
||||
|
||||
### Coverage Metrics
|
||||
|
||||
```
|
||||
Total Coverage: 94.8%
|
||||
Target: 85.0%
|
||||
@@ -171,6 +184,7 @@ Status: PASS (+9.8%)
|
||||
```
|
||||
|
||||
### Test Execution
|
||||
|
||||
```
|
||||
Total Tests: 47
|
||||
Passed: 47
|
||||
@@ -179,6 +193,7 @@ Duration: 1.566s
|
||||
```
|
||||
|
||||
### Key Test Scenarios Validated
|
||||
|
||||
✅ Single-credential backward compatibility
|
||||
✅ Multi-credential exact match (example.com)
|
||||
✅ Multi-credential wildcard match (*.example.com)
|
||||
@@ -193,32 +208,40 @@ Duration: 1.566s
|
||||
## Architecture Decisions
|
||||
|
||||
### 1. Two-Phase Processing
|
||||
|
||||
**Rationale:** Separates provider detection from credential resolution, enabling cleaner code and better error handling.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- **Phase 1:** Build provider config list, detect multi-credential flag
|
||||
- **Phase 2:** Resolve per-domain credentials using helper function
|
||||
|
||||
### 2. Interface-Based Design
|
||||
|
||||
**Rationale:** Enables comprehensive testing without real Caddy server dependency.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- Created `CaddyClient` interface
|
||||
- Modified `NewManager` signature to accept interface
|
||||
- Implemented `MockClient` for testing
|
||||
|
||||
### 3. Credential Resolution Priority
|
||||
|
||||
**Rationale:** Provides flexible matching while ensuring most specific match wins.
|
||||
|
||||
**Priority Order:**
|
||||
|
||||
1. Exact match (example.com → example.com)
|
||||
2. Wildcard match (app.example.com → *.example.com)
|
||||
3. Catch-all (any domain → empty zone_filter)
|
||||
|
||||
### 4. Backward Compatibility First
|
||||
|
||||
**Rationale:** Existing single-credential deployments must continue working unchanged.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- Preserved original code paths
|
||||
- Conditional branching based on `UseMultiCredentials` flag
|
||||
- Comprehensive backward compatibility test
|
||||
@@ -226,12 +249,15 @@ Duration: 1.566s
|
||||
## Security Considerations
|
||||
|
||||
### Encryption
|
||||
|
||||
- AES-256-GCM for all stored credentials
|
||||
- Base64 encoding for database storage
|
||||
- Proper key version management
|
||||
|
||||
### Audit Trail
|
||||
|
||||
Every credential selection logs:
|
||||
|
||||
```
|
||||
credential_uuid: <UUID>
|
||||
zone_filter: <filter>
|
||||
@@ -239,6 +265,7 @@ domain: <matched-domain>
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- No credential exposure in error messages
|
||||
- Graceful degradation for missing credentials
|
||||
- Clear error propagation for debugging
|
||||
@@ -246,16 +273,19 @@ domain: <matched-domain>
|
||||
## Performance Impact
|
||||
|
||||
### Database Queries
|
||||
|
||||
- Phase 1: Single query for all DNS providers
|
||||
- Phase 2: Preloaded with Phase 1 data (no additional queries)
|
||||
- Result: **No additional database load**
|
||||
|
||||
### Memory Footprint
|
||||
|
||||
- `ZoneCredentials` map: ~100 bytes per domain
|
||||
- Typical deployment (10 domains): ~1KB additional memory
|
||||
- Result: **Negligible impact**
|
||||
|
||||
### Config Generation
|
||||
|
||||
- Multi-credential: O(n) policies where n = domain count
|
||||
- Single-credential: O(1) policy (unchanged)
|
||||
- Result: **Linear scaling, acceptable for typical use cases**
|
||||
@@ -263,6 +293,7 @@ domain: <matched-domain>
|
||||
## Files Modified
|
||||
|
||||
### Core Implementation
|
||||
|
||||
1. `backend/internal/caddy/manager.go` (Modified)
|
||||
- Added struct fields
|
||||
- Created CaddyClient interface
|
||||
@@ -279,29 +310,33 @@ domain: <matched-domain>
|
||||
- No modifications required
|
||||
|
||||
### Testing
|
||||
4. `backend/internal/caddy/manager_multicred_integration_test.go` (NEW)
|
||||
|
||||
1. `backend/internal/caddy/manager_multicred_integration_test.go` (NEW)
|
||||
- 4 comprehensive integration tests
|
||||
- Helper functions for setup and validation
|
||||
- MockClient implementation
|
||||
|
||||
5. `backend/internal/caddy/manager_multicred_test.go` (Modified)
|
||||
2. `backend/internal/caddy/manager_multicred_test.go` (Modified)
|
||||
- Removed redundant unit tests
|
||||
- Added documentation comment explaining integration test coverage
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
### Single-Credential Providers
|
||||
|
||||
- **Behavior:** Unchanged
|
||||
- **Config:** Single TLS policy for all domains
|
||||
- **Credentials:** Shared across all domains
|
||||
- **Test Coverage:** Dedicated test validates this path
|
||||
|
||||
### Database Schema
|
||||
|
||||
- **New Fields:** `use_multi_credentials` (default: false)
|
||||
- **Migration:** Existing providers default to single-credential mode
|
||||
- **Impact:** Zero for existing deployments
|
||||
|
||||
### API Endpoints
|
||||
|
||||
- **Changes:** None required
|
||||
- **Client Impact:** None
|
||||
- **Deployment:** No coordination needed
|
||||
@@ -309,22 +344,26 @@ domain: <matched-domain>
|
||||
## Manual Verification Checklist
|
||||
|
||||
### Helper Functions ✅
|
||||
|
||||
- [x] `extractBaseDomain` strips wildcard prefix correctly
|
||||
- [x] `matchesZoneFilter` handles exact, wildcard, and catch-all
|
||||
- [x] `getCredentialForDomain` implements 3-priority resolution
|
||||
|
||||
### Integration Flow ✅
|
||||
|
||||
- [x] Phase 1 detects multi-credential providers
|
||||
- [x] Phase 2 resolves credentials per domain
|
||||
- [x] Config generation creates separate policies
|
||||
- [x] Backward compatibility maintained
|
||||
|
||||
### Audit Logging ✅
|
||||
|
||||
- [x] credential_uuid logged for each selection
|
||||
- [x] zone_filter logged for audit trail
|
||||
- [x] domain logged for troubleshooting
|
||||
|
||||
### Error Handling ✅
|
||||
|
||||
- [x] Missing credentials handled gracefully
|
||||
- [x] Encryption errors propagate clearly
|
||||
- [x] No credential exposure in error messages
|
||||
@@ -332,40 +371,48 @@ domain: <matched-domain>
|
||||
## Definition of Done
|
||||
|
||||
✅ **DNSProviderConfig struct has new fields**
|
||||
|
||||
- `UseMultiCredentials` bool added
|
||||
- `ZoneCredentials` map added
|
||||
|
||||
✅ **ApplyConfig resolves credentials per-domain**
|
||||
|
||||
- Phase 2 loop implemented
|
||||
- Uses `getCredentialForDomain` helper
|
||||
- Builds `ZoneCredentials` map
|
||||
|
||||
✅ **buildDNSChallengeIssuer uses zone-specific credentials**
|
||||
|
||||
- Conditional branching on `UseMultiCredentials`
|
||||
- Separate TLS policies per domain in multi-credential mode
|
||||
- Single policy preserved for single-credential mode
|
||||
|
||||
✅ **Integration tests implemented**
|
||||
|
||||
- 4 comprehensive test scenarios
|
||||
- All scenarios passing
|
||||
- Helper functions for setup and validation
|
||||
|
||||
✅ **Backward compatibility maintained**
|
||||
|
||||
- Single-credential providers work unchanged
|
||||
- Dedicated test validates backward compatibility
|
||||
- No breaking changes
|
||||
|
||||
✅ **Coverage ≥85%**
|
||||
|
||||
- Achieved: 94.8%
|
||||
- Target: 85.0%
|
||||
- Status: PASS (+9.8%)
|
||||
|
||||
✅ **Audit logging implemented**
|
||||
|
||||
- credential_uuid logged
|
||||
- zone_filter logged
|
||||
- domain logged
|
||||
|
||||
✅ **Manual verification complete**
|
||||
|
||||
- All helper functions tested
|
||||
- Integration flow validated
|
||||
- Error handling verified
|
||||
@@ -374,6 +421,7 @@ domain: <matched-domain>
|
||||
## Usage Examples
|
||||
|
||||
### Single-Credential Provider (Backward Compatible)
|
||||
|
||||
```go
|
||||
provider := DNSProvider{
|
||||
ProviderType: "cloudflare",
|
||||
@@ -384,6 +432,7 @@ provider := DNSProvider{
|
||||
```
|
||||
|
||||
### Multi-Credential Provider (New Feature)
|
||||
|
||||
```go
|
||||
provider := DNSProvider{
|
||||
ProviderType: "cloudflare",
|
||||
@@ -398,6 +447,7 @@ provider := DNSProvider{
|
||||
```
|
||||
|
||||
### Credential Resolution Flow
|
||||
|
||||
```
|
||||
1. Domain: test1.example.com
|
||||
-> Extract base: example.com
|
||||
@@ -421,10 +471,12 @@ provider := DNSProvider{
|
||||
## Deployment Notes
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Database migration adds `use_multi_credentials` column (default: false)
|
||||
- Existing providers automatically use single-credential mode
|
||||
|
||||
### Rollout Strategy
|
||||
|
||||
1. Deploy backend with new code
|
||||
2. Existing providers continue working (backward compatible)
|
||||
3. Enable multi-credential mode per provider via admin UI
|
||||
@@ -432,12 +484,15 @@ provider := DNSProvider{
|
||||
5. Caddy config regenerates automatically on next apply
|
||||
|
||||
### Rollback Procedure
|
||||
|
||||
If rollback needed:
|
||||
|
||||
1. Set `use_multi_credentials=false` on all providers
|
||||
2. Deploy previous backend version
|
||||
3. No data loss, graceful degradation
|
||||
|
||||
### Monitoring
|
||||
|
||||
- Check audit logs for credential selection
|
||||
- Monitor Caddy config generation time
|
||||
- Watch for "failed to resolve credentials" errors
|
||||
@@ -445,6 +500,7 @@ If rollback needed:
|
||||
## Future Enhancements
|
||||
|
||||
### Potential Improvements
|
||||
|
||||
1. **Web UI for Multi-Credential Management**
|
||||
- Add/edit/delete credentials per provider
|
||||
- Zone filter validation
|
||||
@@ -470,6 +526,7 @@ If rollback needed:
|
||||
The Phase 3 Caddy Manager multi-credential integration is **COMPLETE** and **PRODUCTION-READY**. All requirements met, comprehensive testing in place, and backward compatibility ensured.
|
||||
|
||||
**Key Achievements:**
|
||||
|
||||
- ✅ 94.8% test coverage (9.8% above target)
|
||||
- ✅ 47/47 tests passing
|
||||
- ✅ Full backward compatibility
|
||||
@@ -478,6 +535,7 @@ The Phase 3 Caddy Manager multi-credential integration is **COMPLETE** and **PRO
|
||||
- ✅ Production-grade error handling
|
||||
|
||||
**Next Steps:**
|
||||
|
||||
1. Deploy to staging environment for integration testing
|
||||
2. Perform end-to-end testing with real DNS providers
|
||||
3. Validate SSL certificate generation with zone-specific credentials
|
||||
|
||||
Reference in New Issue
Block a user