mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-14 12:39:29 +00:00
feat(ssh,wincertstore,javakeystore,k8ssecret): explicit ValidateOnly + leverage existing connectors
Phase 9 of the deploy-hardening I master bundle. The four non-file-server connectors get real ValidateOnly probes that operators use to preview a deploy without touching the live cert. Existing DeployCertificate paths already have explicit backup + rollback semantics (SCP backup / WinCertStore Get-ChildItem snapshot / keytool snapshot / K8s atomic API). SSH (validate_only.go): - Probes via SSHClient.Connect. Confirms agent reachability + credentials. Cheap (no remote command runs); released cleanly via defer Close. - A true SCP dry-run requires a no-commit upload (SCP doesn't have one). V2 ships the auth probe as the load-bearing check. - 3 new tests in validate_only_test.go. WinCertStore (validate_only.go): - Probes via PowerShell `Get-ChildItem -Path Cert:\<loc>\<store>` using the configured StoreLocation + StoreName (defaults LocalMachine\My). - Confirms agent has Windows + the IIS module + the right ACLs. - 4 new tests including default-store-path verification. JavaKeystore (validate_only.go): - Probes via `keytool -list -keystore <path> -storepass <pass>` using the configured KeystorePath / KeystorePassword and KeytoolPath (default "keytool"). - Confirms keystore exists, password is correct, JRE is on PATH. - 4 new tests covering succeeds / fails / no-path-sentinel / nil-executor-sentinel. K8s Secret (validate_only.go): - Probes via K8sClient.GetSecret on the configured Namespace + SecretName. Returns nil on success or "not found" (the CreateSecret path on Deploy will handle it). Other errors (forbidden/unreachable) surface as wrapped. - 4 new tests covering succeeds / RBAC-error wrapped / no-config-sentinel / nil-client-sentinel. Smoke test connectorsAtPhase3 list shrunk from 7 to 3 entries (ssh + wincertstore + javakeystore + k8ssecret removed). Only caddy (file-mode) + envoy + traefik remain — those three genuinely have no validate-with-target command available. Race detector clean across all 13 connectors. golangci-lint v2.11.4 clean. Phase 10 next: DeployCounters + Prometheus exposer mirroring the production-hardening-II OCSP counter pattern.
This commit is contained in:
@@ -27,13 +27,13 @@ import (
|
||||
// f5 removed Phase 8 — real ValidateOnly implementation now in validate_only.go.
|
||||
// haproxy removed Phase 6 — real ValidateOnly implementation now in haproxy.go.
|
||||
// iis removed Phase 8 — real ValidateOnly implementation now in validate_only.go.
|
||||
"github.com/shankar0123/certctl/internal/connector/target/javakeystore"
|
||||
"github.com/shankar0123/certctl/internal/connector/target/k8ssecret"
|
||||
// javakeystore removed Phase 9 — real ValidateOnly implementation now in validate_only.go.
|
||||
// k8ssecret removed Phase 9 — real ValidateOnly implementation now in validate_only.go.
|
||||
// nginx removed Phase 4 — real ValidateOnly implementation now in nginx.go.
|
||||
// postfix removed Phase 7 — real ValidateOnly implementation now in postfix.go.
|
||||
"github.com/shankar0123/certctl/internal/connector/target/ssh"
|
||||
// ssh removed Phase 9 — real ValidateOnly implementation now in validate_only.go.
|
||||
"github.com/shankar0123/certctl/internal/connector/target/traefik"
|
||||
"github.com/shankar0123/certctl/internal/connector/target/wincertstore"
|
||||
// wincertstore removed Phase 9 — real ValidateOnly implementation now in validate_only.go.
|
||||
)
|
||||
|
||||
// connectorsAtPhase3 is the canonical list of connectors that, as
|
||||
@@ -74,20 +74,20 @@ var connectorsAtPhase3 = []struct {
|
||||
// f5 removed Phase 8 — Authenticate-probe real impl.
|
||||
// haproxy removed Phase 6 — `haproxy -c -f` real impl.
|
||||
// iis removed Phase 8 — Get-WebSite probe real impl.
|
||||
{"javakeystore", func() target.Connector { return &javakeystore.Connector{} }},
|
||||
{"k8ssecret", func() target.Connector { return &k8ssecret.Connector{} }},
|
||||
// javakeystore removed Phase 9 — `keytool -list` real impl.
|
||||
// k8ssecret removed Phase 9 — GetSecret RBAC probe real impl.
|
||||
// nginx removed Phase 4 — `nginx -t` real impl.
|
||||
// postfix removed Phase 7 — `postfix check` / `doveconf -n` real impl.
|
||||
{"ssh", func() target.Connector { return &ssh.Connector{} }},
|
||||
// ssh removed Phase 9 — Connect probe real impl.
|
||||
// traefik: no validate-with-target command exists; always sentinel.
|
||||
{"traefik", func() target.Connector { return &traefik.Connector{} }},
|
||||
{"wincertstore", func() target.Connector { return &wincertstore.Connector{} }},
|
||||
// wincertstore removed Phase 9 — `Get-ChildItem Cert:\` probe.
|
||||
}
|
||||
|
||||
func TestEveryConnectorDefaultsToSentinel(t *testing.T) {
|
||||
// Expected list size shrinks as Phases 4-9 land their real
|
||||
// ValidateOnly implementations. Phase 4 removed nginx.
|
||||
const expectedAtCurrentPhase = 7
|
||||
const expectedAtCurrentPhase = 3
|
||||
if len(connectorsAtPhase3) != expectedAtCurrentPhase {
|
||||
t.Fatalf("connectors-at-phase list = %d entries, want %d (drift in the 13-connector inventory)", len(connectorsAtPhase3), expectedAtCurrentPhase)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user