mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-13 02:58:51 +00:00
62d03d9134
Follow-up to6119f26(awsacmpca: replace stub client with AWS SDK v2 implementation). CI's golangci-lint contextcheck rule flagged six violations in awsacmpca_test.go where mustNew/awsacmpca.New were called from test functions that had ctx in scope but didn't thread it through New(). The previous commit used context.Background() inside New() with the rationale that "the audit allows either threading or documenting the limitation"; CI made that choice for us. Threading ctx is the right shape per the audit's stated preference. The fix cascades from awsacmpca.New through issuerfactory.NewFromConfig and IssuerRegistry.Rebuild because the contextcheck rule propagates upward through every caller that has ctx in scope. This commit: - Changes awsacmpca.New(config, logger) to awsacmpca.New(ctx, config, logger). The ctx is passed to buildSDKClient → awsconfig.LoadDefaultConfig so SDK credential chain resolution honors caller deadlines (LoadDefaultConfig may probe IMDS or remote credential sources). The doc-comment on New explains that callers without a useful deadline should pass context.Background() and that the SDK has internal credential-resolution timeouts. - Adds ctx as the first parameter of issuerfactory.NewFromConfig. Currently only the AWSACMPCA branch uses ctx (it's threaded into awsacmpca.New); the other 11 branches accept ctx without using it. This is a contractual change that lets callers thread ctx through without contextcheck warnings, even though most issuer constructors do no ctx-aware work today. - Adds ctx as the first parameter of IssuerRegistry.Rebuild. Rebuild iterates over configs and calls NewFromConfig per issuer; the same ctx flows through every connector instantiation. - Updates the two production call sites in internal/service: - issuer.go:279 (TestIssuer connection test) now passes its method-scoped ctx - issuer.go:303 (BuildRegistry) now passes its method-scoped ctx to Rebuild - Updates 13 test sites in internal/connector/issuerfactory/factory_test.go via a new testCtx() helper that returns context.Background(). Helper is dedicated to this file so contextcheck's "you have a ctx in scope, pass it" rule doesn't fire on test functions that don't otherwise need ctx. - Updates 6 test sites in internal/service/issuer_registry_test.go to pass context.Background() to Rebuild. - Removes the now-stale "// NewFromConfig has no ctx parameter (preserved across all 12 connectors); pass context.Background() ..." comment from the awsacmpca branch in factory.go — that workaround is no longer the design. Verified locally: - gofmt -l . clean - go vet ./... clean - staticcheck ./... clean - golangci-lint run --timeout 5m ./... clean (was failing with 6 contextcheck issues before the cascade; now 0 issues) - go test -short -count=1 across all changed packages green Sandbox couldn't run the existing CI's full make verify due to disk pressure on /sessions and a virtiofs concurrent-open-file ceiling on go mod tidy; operator should run `make verify` on the workstation to confirm. Audit reference: cowork/issuer-coverage-audit-2026-05-01/RESULTS.md Top-10 fix #1 (CI follow-up; behavior unchanged from6119f26).
131 lines
4.5 KiB
Go
131 lines
4.5 KiB
Go
package issuerfactory
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/shankar0123/certctl/internal/connector/issuer"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/acme"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/awsacmpca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/digicert"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/ejbca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/entrust"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/globalsign"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/googlecas"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/local"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/openssl"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/sectigo"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/stepca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/vault"
|
|
)
|
|
|
|
// NewFromConfig instantiates an issuer connector from its type string and config JSON.
|
|
// The config JSON keys use snake_case matching the connector Config struct json tags.
|
|
// This replaces the manual wiring in cmd/server/main.go.
|
|
//
|
|
// ctx is currently used only by the AWSACMPCA branch (passed to
|
|
// awsconfig.LoadDefaultConfig for SDK credential chain resolution). Other
|
|
// connectors take no context at construction; the parameter is kept on the
|
|
// signature so callers that have a ctx in scope thread it through cleanly
|
|
// (contextcheck linter).
|
|
func NewFromConfig(ctx context.Context, issuerType string, configJSON json.RawMessage, logger *slog.Logger) (issuer.Connector, error) {
|
|
if len(configJSON) == 0 {
|
|
configJSON = []byte("{}")
|
|
}
|
|
|
|
switch issuerType {
|
|
case "local", "local_ca", "GenericCA", "genericca":
|
|
var cfg local.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Local CA config: %w", err)
|
|
}
|
|
return local.New(&cfg, logger), nil
|
|
|
|
case "ACME", "acme":
|
|
var cfg acme.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid ACME config: %w", err)
|
|
}
|
|
return acme.New(&cfg, logger), nil
|
|
|
|
case "StepCA", "stepca":
|
|
var cfg stepca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid step-ca config: %w", err)
|
|
}
|
|
return stepca.New(&cfg, logger), nil
|
|
|
|
case "OpenSSL", "openssl":
|
|
var cfg openssl.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid OpenSSL config: %w", err)
|
|
}
|
|
return openssl.New(&cfg, logger), nil
|
|
|
|
case "VaultPKI", "vaultpki":
|
|
var cfg vault.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Vault PKI config: %w", err)
|
|
}
|
|
return vault.New(&cfg, logger), nil
|
|
|
|
case "DigiCert", "digicert":
|
|
var cfg digicert.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid DigiCert config: %w", err)
|
|
}
|
|
return digicert.New(&cfg, logger), nil
|
|
|
|
case "Sectigo", "sectigo":
|
|
var cfg sectigo.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Sectigo config: %w", err)
|
|
}
|
|
return sectigo.New(&cfg, logger), nil
|
|
|
|
case "GoogleCAS", "googlecas":
|
|
var cfg googlecas.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Google CAS config: %w", err)
|
|
}
|
|
return googlecas.New(&cfg, logger), nil
|
|
|
|
case "AWSACMPCA", "awsacmpca":
|
|
var cfg awsacmpca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid AWS ACM PCA config: %w", err)
|
|
}
|
|
conn, err := awsacmpca.New(ctx, &cfg, logger)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("AWS ACM PCA init: %w", err)
|
|
}
|
|
return conn, nil
|
|
|
|
case "Entrust", "entrust":
|
|
var cfg entrust.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Entrust config: %w", err)
|
|
}
|
|
return entrust.New(&cfg, logger), nil
|
|
|
|
case "GlobalSign", "globalsign":
|
|
var cfg globalsign.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid GlobalSign config: %w", err)
|
|
}
|
|
return globalsign.New(&cfg, logger), nil
|
|
|
|
case "EJBCA", "ejbca":
|
|
var cfg ejbca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid EJBCA config: %w", err)
|
|
}
|
|
return ejbca.New(&cfg, logger), nil
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unknown issuer type: %q", issuerType)
|
|
}
|
|
}
|