feat: M25 post-deployment TLS verification + M26 Traefik/Caddy targets

M25: After deploying a certificate, the agent probes the live TLS
endpoint and compares SHA-256 fingerprints to verify the correct cert
is being served. Best-effort — failures don't block deployments.
New endpoints: POST /jobs/{id}/verify, GET /jobs/{id}/verification.
Migration 000008 adds verification columns to jobs table.

M26: Traefik target connector (file provider, auto-reload) and Caddy
target connector (dual-mode: admin API hot-reload or file-based).
Both wired into agent dispatch.

Also: restructured README to highlight supported integrations (issuers,
targets, notifiers) earlier, moved API/CLI/MCP sections lower. Updated
all docs (features, connectors, architecture, testing guide, why-certctl)
and fixed integration tests for 18-param RegisterHandlers signature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-03-27 21:07:16 -04:00
parent ef92b07448
commit be72627aeb
28 changed files with 3365 additions and 177 deletions
+13
View File
@@ -81,6 +81,7 @@ func TestCertificateLifecycle(t *testing.T) {
healthHandler := handler.NewHealthHandler("none")
discoveryHandler := handler.NewDiscoveryHandler(&mockDiscoveryService{})
networkScanHandler := handler.NewNetworkScanHandler(&mockNetworkScanService{})
verificationHandler := handler.NewVerificationHandler(&mockVerificationService{})
// EST handler — uses real Local CA issuer via ESTService
estService := service.NewESTService("iss-local", issuerRegistry["iss-local"], auditService, logger)
@@ -106,6 +107,7 @@ func TestCertificateLifecycle(t *testing.T) {
healthHandler,
discoveryHandler,
networkScanHandler,
verificationHandler,
)
r.RegisterESTHandlers(estHandler)
@@ -1208,3 +1210,14 @@ func (m *mockNetworkScanService) DeleteTarget(ctx context.Context, id string) er
func (m *mockNetworkScanService) TriggerScan(ctx context.Context, targetID string) (*domain.DiscoveryScan, error) {
return nil, nil
}
// mockVerificationService implements handler.VerificationService for integration tests.
type mockVerificationService struct{}
func (m *mockVerificationService) RecordVerificationResult(ctx interface{}, result *domain.VerificationResult) error {
return nil
}
func (m *mockVerificationService) GetVerificationResult(ctx interface{}, jobID string) (*domain.VerificationResult, error) {
return nil, fmt.Errorf("not found")
}
+2
View File
@@ -74,6 +74,7 @@ func setupTestServer(t *testing.T) (*httptest.Server, *mockCertificateRepository
healthHandler := handler.NewHealthHandler("none")
discoveryHandler := handler.NewDiscoveryHandler(&mockDiscoveryService{})
networkScanHandler := handler.NewNetworkScanHandler(&mockNetworkScanService{})
verificationHandler := handler.NewVerificationHandler(&mockVerificationService{})
// EST handler — uses real Local CA issuer via ESTService
estService := service.NewESTService("iss-local", issuerRegistry["iss-local"], auditService, logger)
@@ -98,6 +99,7 @@ func setupTestServer(t *testing.T) (*httptest.Server, *mockCertificateRepository
healthHandler,
discoveryHandler,
networkScanHandler,
verificationHandler,
)
r.RegisterESTHandlers(estHandler)