feat(M34): dynamic issuer configuration with encrypted config storage

Replace static env-var-based issuer wiring with GUI-driven dynamic
configuration stored encrypted in PostgreSQL. Operators can now
configure, test, enable/disable, and manage issuers from the dashboard
without restarting the server.

Key changes:
- AES-256-GCM encryption for sensitive issuer config at rest (PBKDF2
  key derivation with 100k iterations)
- Dynamic IssuerRegistry with sync.RWMutex replacing static map
- Connector factory pattern (issuerfactory.NewFromConfig) replacing
  140 lines of static wiring in main.go
- Migration 000009: encrypted_config, last_tested_at, test_status,
  source columns on issuers table
- Env var seeding on first boot with ON CONFLICT DO NOTHING
- Registry Rebuild() for atomic map swap after CRUD operations
- Issuer type validation against domain constants on Create
- Audit trail for test connection results
- Conditional seeding for step-ca/OpenSSL (only when env vars set)
- GUI: source badge, connection test status on issuer detail page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-04-04 00:20:13 -04:00
parent 9954fd1100
commit 995b72df05
36 changed files with 1859 additions and 361 deletions
+3 -1
View File
@@ -3,6 +3,7 @@ package service
import (
"context"
"fmt"
"log/slog"
"sync"
"testing"
@@ -130,13 +131,14 @@ func TestConcurrentAgentHeartbeats(t *testing.T) {
mockAgentRepo.AddAgent(agent)
}
issuerRegistry := NewIssuerRegistry(slog.Default())
agentSvc := NewAgentService(
mockAgentRepo,
nil, // certRepo
nil, // jobRepo
nil, // targetRepo
nil, // auditService
make(map[string]IssuerConnector),
issuerRegistry,
nil, // renewalService
)