mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:11:31 +00:00
auth-bundle-2 Phase 0: dependency-add + oidc auth-type literal + runtime guard
Bundle 2 Phase 0 stages the dependencies + auth-type discriminator
literal that later phases consume. No handler chain wired yet; an
operator who sets CERTCTL_AUTH_TYPE=oidc on this commit gets a clear
refuse-to-start error rather than a silent fallback to api-key (the
G-1 failure mode that drove "jwt" out of the allowed set).
Deliverables:
* go.mod: github.com/coreos/go-oidc/v3 v3.18.0 added as a direct
require. Per the pre-bundle dependency audit (Apache-2.0, zero CVEs
ever per OSV.dev, 2,400+ stars, used by Hashicorp Vault + Dex +
Hydra + Authentik + every Kubernetes OIDC integration), this is the
ecosystem-standard Go OIDC client. Pinned to a specific minor
(v3.18.0) per the prompt's "no bare latest" rule.
* go.mod: golang.org/x/oauth2 promoted from // indirect to direct,
bumped from v0.34.0 to v0.36.0 by go mod tidy. Both versions are
OSV-clean. Maintained by the Go team.
* No JSON-path library added (forbidden by the dependency audit; the
group-claim resolver is hand-rolled in Phase 3).
* internal/config/config.go: AuthTypeOIDC constant added with a
load-bearing comment explaining (a) this is the AUTH-TYPE literal,
not a JWT alg literal, so the G-1 closure invariant is preserved
("jwt" stays out of ValidAuthTypes forever); (b) the runtime guard
in cmd/server/main.go intentionally refuses-to-start when oidc is
set pre-Phase-6 to avoid the silent-downgrade failure mode.
ValidAuthTypes() now returns {api-key, none, oidc}.
* internal/config/config_test.go: TestValidAuthTypesIsExactly_APIKey_None
renamed to TestValidAuthTypesIsExactly_APIKey_None_OIDC and now pins
the 3-entry set. TestValidAuthTypesDoesNotContainJWT (G-1 closure
test) still passes because "jwt" is never added back.
TestValidate_GenericInvalidAuthType's bad-types list updated:
"oidc" removed (now valid), "saml" added (correctly rejected per
Decision 5's SAML deferral).
* cmd/server/main.go: defense-in-depth runtime auth-type guard now
has an explicit AuthTypeOIDC case that exit(1)s with an actionable
message: "the OIDC auth chain is not yet wired in this build (Auth
Bundle 2 Phase 6 ships the session middleware that consumes this
auth-type literal)." This closes the lying-field gap the literal
would otherwise create. Phase 6 of Bundle 2 relaxes this case to
fall through alongside api-key + none.
* api/openapi.yaml: /v1/auth/info auth_type enum extended from
[api-key, none] to [api-key, none, oidc] with an in-line comment
explaining the Phase-0-vs-Phase-6 timing so an OpenAPI consumer
isn't surprised by "oidc" appearing here pre-Bundle-2-merge.
* deploy/helm/certctl/templates/_helpers.tpl::certctl.validateAuthType:
valid set extended to include "oidc". Chart-time validation now
passes for type=oidc; the binary's runtime guard takes over to
refuse the start. Once Bundle 2 ships, the runtime guard relaxes
and OIDC works end-to-end with no further chart edits.
* .env.example: CERTCTL_AUTH_TYPE comment block updated to document
the three valid values + the Phase-0-vs-Phase-6 timing.
* internal/auth/oidc/doc.go: new package directory with package doc
+ transitional blank imports for coreos/go-oidc/v3 + x/oauth2 so
go mod tidy keeps both deps as direct requires until Phase 3's
service.go replaces the blanks with real symbol use. Doc explains
the package layout (oidc/ + oidc/domain/ + oidc/groupclaim/ +
oidc/testfixtures/) so the post-Bundle-2 reader can navigate.
Verifications:
* gofmt clean on every changed file.
* go vet clean on internal/config + cmd/server + internal/auth/oidc.
* go test -short -count=1 green on internal/config (including the
G-1 closure + new validation tests), cmd/server, internal/auth (all
Bundle 1 packages), internal/service/auth.
* govulncheck ./... clean (M-024 hard CI gate).
* All 24 ci-guards pass locally.
Phase 0 exit criteria from cowork/auth-bundle-2-prompt.md:
* go.mod shows coreos/go-oidc/v3 as direct: yes.
* golang.org/x/oauth2 is direct (not indirect): yes.
* govulncheck ./... clean: yes.
* No JSON-path library in go.mod / go.sum deltas: confirmed (only
v3 of go-oidc + the x/oauth2 bump landed).
* make verify green: gofmt + vet + go test pass; full make verify
(which would invoke golangci-lint) deferred to CI since the
sandbox doesn't have golangci-lint installed; the operator runs
make verify locally before pushing per CLAUDE.md operating rule.
This commit is contained in:
@@ -1507,6 +1507,22 @@ const (
|
||||
// and set this value on the upstream certctl process. See
|
||||
// docs/architecture.md "Authenticating-gateway pattern".
|
||||
AuthTypeNone AuthType = "none"
|
||||
|
||||
// AuthTypeOIDC (Auth Bundle 2 Phase 0) reserves the literal that the
|
||||
// OIDC handler chain (Bundle 2 Phase 5+6) consumes. Pre-Bundle-2
|
||||
// behavior: the literal is allowed by the validator but the handler
|
||||
// chain is not yet wired, so the runtime guard in cmd/server/main.go
|
||||
// surfaces a clear "oidc auth-type configured but Bundle 2 handlers
|
||||
// not registered" error rather than silently falling back to api-key
|
||||
// (the failure mode that drove G-1's jwt-literal removal). Once
|
||||
// Bundle 2's session middleware + OIDC service ship, the runtime
|
||||
// guard relaxes and CERTCTL_AUTH_TYPE=oidc routes through them.
|
||||
//
|
||||
// Note: this is the AUTH-TYPE literal value, NOT the JWT alg literal.
|
||||
// ID tokens are JWTs internally but the auth-type config string is
|
||||
// "oidc". The G-1 closure test (TestValidAuthTypesDoesNotContainJWT)
|
||||
// stays passing because "jwt" is never added back to the slice.
|
||||
AuthTypeOIDC AuthType = "oidc"
|
||||
)
|
||||
|
||||
// ValidAuthTypes returns the allowed CERTCTL_AUTH_TYPE values. The set is
|
||||
@@ -1515,8 +1531,14 @@ const (
|
||||
// validator below, the runtime guard in cmd/server/main.go, the helm
|
||||
// chart template (`certctl.validateAuthType`), and the property test in
|
||||
// config_test.go that pins "jwt" out of the slice forever.
|
||||
//
|
||||
// Bundle 2 Phase 0 adds AuthTypeOIDC to the slice. The G-1 invariant
|
||||
// remains: "jwt" stays out of the allowed set forever; OIDC ID tokens
|
||||
// are JWTs internally but the auth-type literal is "oidc", so the
|
||||
// silent-downgrade attack surface that "jwt" represented does not
|
||||
// regress.
|
||||
func ValidAuthTypes() []AuthType {
|
||||
return []AuthType{AuthTypeAPIKey, AuthTypeNone}
|
||||
return []AuthType{AuthTypeAPIKey, AuthTypeNone, AuthTypeOIDC}
|
||||
}
|
||||
|
||||
// AuthConfig contains authentication configuration.
|
||||
|
||||
Reference in New Issue
Block a user