Skip to content

Commit 3413cc2

Browse files
committed
Define SPIFFE trust configuration
Both SPIFFE credential methods (X.509-SVID and JWT-SVID) need one fail-closed identity and association model before authentication can produce equivalent authorization outcomes for either method. Without a shared model, adding live SVID verification later would force a choice between duplicating trust-domain/scope/audience checks per credential type or bolting authorization onto whichever method lands first. This commit defines that model as pure config validation, deliberately without loading trust bundles or authenticating credentials — those are separate, later steps on this stacked branch (refs #6200). It is, however, independently fail-closed: `RunConfig.Validate()` now validates `spiffe_trust_domains`/`inbound_grants.spiffe_client_auth` directly, and `Config.SPIFFETrust` is built in the embedded auth server constructor, so a malformed or half-configured declaration cannot start successfully and silently have no effect. `SPIFFETrustDomainRunConfig` declares a named trust domain, the credential methods it enables, and exactly one bundle source: a SPIFFE Bundle Endpoint (an HTTPS URL plus an `https_web`/`https_spiffe` authentication profile, so a future loader knows whether to trust the endpoint's TLS connection via Web PKI or a separately distributed X.509-SVID root) or the local Workload API. Both are validated for shape now so the field exists in the authoritative model before consumption is built, even though fetching a bundle is out of scope here. `SPIFFEClientAuthRunConfig` associates a SPIFFE principal pattern (a concrete ID or a terminal `/*` wildcard) within a declared trust domain with an explicit OAuth client_id, methods, and permissions — client_id is never derived from the SPIFFE ID, so an operator always states which OAuth identity a workload maps to. Permissions are three independent dimensions instead of one combined list: `resources` (RFC 8707, optional, must be an absolute HTTP(S) URI and a member of the server's `allowed_audiences` allowlist — the same list `DelegateClientRunConfig.Audiences` is validated against), `audiences` (RFC 8693, required, but deliberately *not* bounded by that allowlist since a token audience is a distinct request dimension from a resource and may be a non-URI logical identifier), and `grant_types` (required, must be exactly token-exchange for now) — so permitting a resource never implies permitting the same value as an audience, or vice versa, and client authentication never by itself confers a grant. `NewSPIFFETrustConfig` validates and normalizes these declarations into an immutable `SPIFFETrustConfig`. It retains the validated, canonicalized trust-domain records (not just the association policy), exposed via a lookup-by-name method, so a future X.509/JWT-SVID validator has one authoritative source for a trust domain's canonical form, enabled methods, and bundle source instead of re-parsing the raw RunConfig separately. Its zero value is also valid (equivalent to what the constructor returns for empty input), so external packages may construct it directly without going through the constructor. Validation fails closed on anything that could make authorization ambiguous or order-dependent: duplicate trust-domain names or canonical trust domains, a principal whose trust domain doesn't match its declared trust-domain reference, overlapping principal patterns across associations (segment-aware, so `/agent/*` doesn't collide with `/agent-x/*`), client IDs colliding with the reserved synthetic-client namespace or matching a client metadata document URL (reserved for CIMD-resolved clients, checked with the same predicate the runtime CIMD router uses), a bundle source whose declared type doesn't match its payload, and a bundle endpoint whose authentication profile is missing or unrecognized. A valid, non-empty configuration still has no runtime effect in this commit: nothing yet registers a client or verifies a credential against it. That first consumer (static client registration) lands in a later commit on this stack; live SVID/bundle verification is a further step beyond it. Since no part of this epic as currently drafted verifies an SVID against the configured bundle, `RunConfig.Validate()` hard-rejects a non-empty `spiffe_trust_domains` outright rather than accepting it silently: an operator must not be able to believe SPIFFE client authentication is active when no credential is ever checked. The follow-up that adds real verification removes this rejection. Refs #6200 Signed-off-by: Jakub Hrozek <jakub@stacklok.com>
1 parent 65eaa1b commit 3413cc2

10 files changed

Lines changed: 1594 additions & 4 deletions

File tree

docs/server/docs.go

Lines changed: 135 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/server/swagger.json

Lines changed: 135 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)