Skip to content

feat: nodeauth — local projected-token verification against cluster JWKS - #21

Merged
kfeofantov merged 1 commit into
mainfrom
feat/nodeauth-token-verify
Aug 10, 2026
Merged

kfeofantov merged 1 commit into
mainfrom
feat/nodeauth-token-verify

Conversation

@kfeofantov

Copy link
Copy Markdown
Contributor

What

Slice 2 of the node→controller inventory channel (ADR 0010). A self-contained, controller-side library that verifies the projected ServiceAccount token the node role will present — locally, against the cluster JWKS, with no TokenReview (so no new RBAC verb).

No wiring in this PR: the HTTP receiver and node client come in slice 3a. This is the crypto/auth core, isolated and heavily unit-tested.

Contents

  • ParseJWKS + KeySet — JWK→crypto.PublicKey conversion (RSA n/e, EC x/y), indexed by kid.
  • HTTPKeySource — OIDC discovery that follows the advertised jwks_uri, over a caller-supplied *http.Client (the controller passes the API server's in-cluster REST transport in 3a).
  • CachingKeySource — caches the key set, refetches once on an unknown kid (models a signing-key rotation).
  • Verifier — asymmetric-only method allow-list (defeats HS256/none algorithm-confusion), expiration required, audience match, optional expected-subject pin to the node ServiceAccount.

Tests

Mint RSA and EC tokens; cover happy path + wrong audience, expired, missing expiry, tampered signature, unknown kid, wrong subject, HS256 algorithm-confusion, and none algorithm. JWKS tests cover discovery, caching (one fetch for a cached kid), and rotation (exactly one refetch on a new kid).

Dependency

Adds github.com/golang-jwt/jwt/v5 — pure-Go, no transitive dependencies. JWKS fetch and JWK→key conversion stay first-party.

🤖 Generated with Claude Code

…WKS (ADR 0010)

The controller-side library that verifies the projected ServiceAccount tokens
the node role will present (ADR 0010). Verification is local: parse the cluster
JWKS (RSA and EC keys), then check each token's signature, expiry, audience, and
subject with golang-jwt/jwt/v5 — no TokenReview, so no new RBAC verb.

- ParseJWKS + KeySet: JWK→crypto key conversion, kid indexing.
- HTTPKeySource: OIDC discovery (follows jwks_uri) over a caller-supplied
  client; the controller will pass the API server's in-cluster REST transport.
- CachingKeySource: caches the key set, refetches once on an unknown kid
  (signing-key rotation).
- Verifier: asymmetric-only method allow-list (defeats HS/none algorithm
  confusion), expiration required, audience match, optional expected-subject
  pin to the node role's ServiceAccount.

Unit tests mint RSA and EC tokens and cover the happy path plus wrong audience,
expired, missing expiry, tampered signature, unknown kid, wrong subject, HS256
confusion, and the none algorithm; JWKS tests cover discovery, caching, and
rotation. golang-jwt/jwt/v5 is pure-Go with no transitive dependencies.

No wiring yet; the receiver and node client land in the next slice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kfeofantov
kfeofantov merged commit 69fb166 into main Aug 10, 2026
3 checks passed
@kfeofantov
kfeofantov deleted the feat/nodeauth-token-verify branch August 10, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant