chore: clean .gitignore cache
This commit is contained in:
@@ -1,188 +0,0 @@
|
||||
# Phase 3 Multi-Credential Integration - Quick Reference
|
||||
|
||||
**Full Plan:** [phase3_caddy_integration_completion.md](./phase3_caddy_integration_completion.md)
|
||||
|
||||
## 3-Step Implementation
|
||||
|
||||
### 1. Add Fields to DNSProviderConfig (manager.go:38-44)
|
||||
|
||||
```go
|
||||
type DNSProviderConfig struct {
|
||||
ID uint
|
||||
ProviderType string
|
||||
PropagationTimeout int
|
||||
Credentials map[string]string // Single-cred mode
|
||||
UseMultiCredentials bool // NEW
|
||||
ZoneCredentials map[string]map[string]string // NEW: map[baseDomain]credentials
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Add Credential Resolution Loop (manager.go:~125)
|
||||
|
||||
Insert after line 125 (after `dnsProviderConfigs` built):
|
||||
|
||||
```go
|
||||
// Phase 2: Resolve zone-specific credentials for multi-credential providers
|
||||
for i := range dnsProviderConfigs {
|
||||
cfg := &dnsProviderConfigs[i]
|
||||
|
||||
// Find provider and check UseMultiCredentials flag
|
||||
var provider *models.DNSProvider
|
||||
for j := range dnsProviders {
|
||||
if dnsProviders[j].ID == cfg.ID {
|
||||
provider = &dnsProviders[j]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if provider == nil || !provider.UseMultiCredentials {
|
||||
continue // Skip single-credential providers
|
||||
}
|
||||
|
||||
// Enable multi-credential mode
|
||||
cfg.UseMultiCredentials = true
|
||||
cfg.ZoneCredentials = make(map[string]map[string]string)
|
||||
|
||||
// Preload credentials
|
||||
if err := m.db.Preload("Credentials").First(provider, provider.ID).Error; err != nil {
|
||||
logger.Log().WithError(err).WithField("provider_id", provider.ID).Warn("failed to preload credentials")
|
||||
continue
|
||||
}
|
||||
|
||||
// Resolve credentials for each host's domain
|
||||
for _, host := range hosts {
|
||||
if !host.Enabled || host.DNSProviderID == nil || *host.DNSProviderID != provider.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
baseDomain := extractBaseDomain(host.DomainNames)
|
||||
if baseDomain == "" || cfg.ZoneCredentials[baseDomain] != nil {
|
||||
continue // Already resolved
|
||||
}
|
||||
|
||||
// Resolve credential for this domain
|
||||
credentials, err := m.getCredentialForDomain(provider.ID, baseDomain, provider)
|
||||
if err != nil {
|
||||
logger.Log().WithError(err).WithField("domain", baseDomain).Warn("credential resolution failed")
|
||||
continue
|
||||
}
|
||||
|
||||
cfg.ZoneCredentials[baseDomain] = credentials
|
||||
logger.Log().WithField("domain", baseDomain).Debug("resolved credential")
|
||||
}
|
||||
|
||||
logger.Log().WithField("domains_resolved", len(cfg.ZoneCredentials)).Info("multi-credential resolution complete")
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Update Config Generation (config.go:~190-198)
|
||||
|
||||
Replace credential assembly logic in DNS challenge policy creation:
|
||||
|
||||
```go
|
||||
// Find DNS provider config
|
||||
dnsConfig, ok := dnsProviderMap[providerID]
|
||||
if !ok {
|
||||
logger.Log().WithField("provider_id", providerID).Warn("DNS provider not found")
|
||||
continue
|
||||
}
|
||||
|
||||
// MULTI-CREDENTIAL MODE: Create separate policy per domain
|
||||
if dnsConfig.UseMultiCredentials && len(dnsConfig.ZoneCredentials) > 0 {
|
||||
for baseDomain, credentials := range dnsConfig.ZoneCredentials {
|
||||
// Find domains matching this base domain
|
||||
var matchingDomains []string
|
||||
for _, domain := range domains {
|
||||
if extractBaseDomain(domain) == baseDomain {
|
||||
matchingDomains = append(matchingDomains, domain)
|
||||
}
|
||||
}
|
||||
if len(matchingDomains) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Build provider config with zone-specific credentials
|
||||
providerConfig := map[string]any{"name": dnsConfig.ProviderType}
|
||||
for key, value := range credentials {
|
||||
providerConfig[key] = value
|
||||
}
|
||||
|
||||
// Build issuer with DNS challenge (same as original, but with zone-specific credentials)
|
||||
var issuers []any
|
||||
// ... (same issuer creation logic as original, using providerConfig)
|
||||
|
||||
// Create TLS automation policy for this domain
|
||||
tlsPolicies = append(tlsPolicies, &AutomationPolicy{
|
||||
Subjects: dedupeDomains(matchingDomains),
|
||||
IssuersRaw: issuers,
|
||||
})
|
||||
|
||||
logger.Log().WithField("base_domain", baseDomain).Debug("created DNS challenge policy")
|
||||
}
|
||||
continue // Skip single-credential logic below
|
||||
}
|
||||
|
||||
// SINGLE-CREDENTIAL MODE: Original logic (backward compatible)
|
||||
providerConfig := map[string]any{"name": dnsConfig.ProviderType}
|
||||
for key, value := range dnsConfig.Credentials {
|
||||
providerConfig[key] = value
|
||||
}
|
||||
// ... (rest of original logic)
|
||||
```
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Run `go test ./internal/caddy -run TestExtractBaseDomain` (should pass)
|
||||
- [ ] Run `go test ./internal/caddy -run TestMatchesZoneFilter` (should pass)
|
||||
- [ ] Run `go test ./internal/caddy -run TestManager_GetCredentialForDomain` (should pass)
|
||||
- [ ] Run `go test ./internal/caddy/...` (all tests should pass after changes)
|
||||
- [ ] Create integration test for multi-credential provider
|
||||
- [ ] Manual test: Create provider with 2+ credentials, verify separate TLS policies
|
||||
|
||||
## Validation Commands
|
||||
|
||||
```bash
|
||||
# Test helpers
|
||||
go test -v ./internal/caddy -run TestExtractBaseDomain
|
||||
go test -v ./internal/caddy -run TestMatchesZoneFilter
|
||||
|
||||
# Test integration
|
||||
go test -v ./internal/caddy/... -count=1
|
||||
|
||||
# Check logs for credential resolution
|
||||
docker logs charon-app 2>&1 | grep "multi-credential"
|
||||
docker logs charon-app 2>&1 | grep "resolved credential"
|
||||
|
||||
# Verify generated Caddy config
|
||||
curl -s http://localhost:2019/config/ | jq '.apps.tls.automation.policies[] | select(.subjects[] | contains("example"))'
|
||||
```
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ All existing tests pass
|
||||
✅ Helper function tests pass
|
||||
✅ Integration tests pass (once added)
|
||||
✅ Manual testing with 2+ domains works
|
||||
✅ Backward compatibility validated
|
||||
✅ Logs show credential selection
|
||||
|
||||
## Rollback
|
||||
|
||||
If issues occur:
|
||||
|
||||
1. Set `UseMultiCredentials=false` on all providers via API
|
||||
2. Restart Charon
|
||||
3. Investigate logs for credential resolution errors
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `backend/internal/caddy/manager.go` - Add fields, add resolution loop
|
||||
- `backend/internal/caddy/config.go` - Update DNS challenge policy generation
|
||||
- `backend/internal/caddy/manager_multicred_integration_test.go` - Add integration tests (new file)
|
||||
|
||||
## Estimated Time
|
||||
|
||||
- Implementation: 2-3 hours
|
||||
- Testing: 1-2 hours
|
||||
- Documentation: 1 hour
|
||||
- **Total: 4-6 hours**
|
||||
Reference in New Issue
Block a user