Skip to content

feat: stamp strategy and groups on every <user>-clientconfig Secret (#42) - #43

Closed
braghettos wants to merge 2 commits into
mainfrom
feat/clientconfig-identity-annotations
Closed

braghettos wants to merge 2 commits into
mainfrom
feat/clientconfig-identity-annotations

Conversation

@braghettos

Copy link
Copy Markdown
Collaborator

Closes #42. Stacked on #41. I'll retarget it to main once #41 merges.

Why

Tenant onboarding (a Kyverno GeneratingPolicy in saas) fires on every <user>-clientconfig Secret, but nothing on them identified the credential. The decision is that authn stamps the identity facts it already knows, and the policy decides from them.

What

Every clientconfig authn writes now carries two annotations, alongside #40's certificate-not-{before,after}:

Annotation Value
authn.krateo.io/strategy basic / ldap / oauth / oidc / serviceaccount; self for authn-clientconfig; unknown only from the backfill
authn.krateo.io/groups the certificate's O=, newline-separated
  • Why newlines: group names can contain commas, e.g. Azure groups passed through verbatim by OIDC.
  • Newline in a group name: the login is refused before any certificate is minted (storage.ValidateGroups).
  • Strategy source: Generator.Generate now takes the issuing strategy, and every route passes its own. authn's own identity gets self from the certificate renewer's annotation sync.
  • Startup backfill (internal/identitybackfill): stamps Secrets that predate these annotations, and never overwrites existing ones.
    • Groups are read from the stored certificate.
    • Strategy is self, serviceaccount (a mapping with that username exists) or basic (a basic User exists); otherwise unknown. "Both a mapping and a basic User exist" is also unknown.
    • An unreadable certificate or a failed lookup means the Secret is skipped and logged, never stamped with a guess.
  • No new RBAC. authn already has list/update on Secrets in its namespace.

Consumer

acmp's onboarding selects positively: it creates a tenant only when the groups contain tenants, and a missing annotation means no onboarding. So the backfill must run (authn 0.28.0) before the demo cutover.

Tests

🤖 Generated with Claude Code

https://claude.ai/code/session_01TLFnUe4HXFphxQNAfqFawZ

braghettos and others added 2 commits October 29, 2026 15:28
…nt/login (#36)

The response's `data` carried the issued identity's full kubeconfig, including
client-key-data (a private key), so printing a success response leaked it. The
response now carries only accessToken, user and groups. The generator still mints the
identity and persists <username>-clientconfig, which plumbing endpoints, snowplow and
bff read from the Secret.

Before the change, a grep across 56 repos found four clients of the endpoint, all
decoding accessToken only: core-provider, its cdc, rest-dynamic-controller and
snowplow. The human strategies are unchanged.

Adds a handler test against a fake apiserver. It asserts that the response has no data
and no client-key-data and that the clientconfig is still minted; it fails on the
previous handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TLFnUe4HXFphxQNAfqFawZ
)

Tenant onboarding fires on every clientconfig Secret, but nothing on them told a
tenant from a platform admin or from authn's own identity. Every clientconfig
authn writes now carries:

- authn.krateo.io/strategy: basic|ldap|oauth|oidc|serviceaccount, or self for
  authn's own identity (via the certificate renewer)
- authn.krateo.io/groups: the certificate's O=, newline-separated, because group
  names can contain commas. A group containing a newline is refused before
  anything is minted.

Generator.Generate now takes the issuing strategy, and every login route passes
its own.

A startup backfill (internal/identitybackfill) stamps Secrets that predate the
annotations and never overwrites existing ones. Groups come from the stored
certificate. Strategy is self, serviceaccount (a mapping with that username
exists) or basic (a basic User exists); otherwise unknown, including when both
exist. A Secret whose certificate or lookup fails is skipped, never stamped with
a guess.

No new RBAC: authn already holds list/update on Secrets in its namespace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TLFnUe4HXFphxQNAfqFawZ
@braghettos

Copy link
Copy Markdown
Collaborator Author

Pre-release e2e of #40 + #41 + #42: pass (18/18)

Setup: kind v1.36 with the signer capped at 20m. The cluster first ran the #40 image and was then upgraded to this branch's tip, so the backfill ran against Secrets the previous image wrote. A legacy fixture (legacy-tenant-clientconfig, a real CSR-signed cert CN=legacy-tenant, O=tenants, no annotations) stood in for an old OIDC login.

Area Result
Backfill (log: scanned=3 stamped=2 skipped=0) authn-clientconfig → self / authn; e2e-identity-clientconfig → serviceaccount / krateo:e2e; legacy-tenant-clientconfig → unknown / tenants
#41 serviceaccount login Response keys ["accessToken","groups","user"], no client-key-data in the body; the Secret still holds the key and is re-stamped serviceaccount
#42 basic login 200, still returns data; Secret stamped basic, groups tenants\nSales, EMEA with the comma intact
#40 still holds serviceaccount JWT lifetime 19m (clamped to the capped cert); renewer running

(authn-clientconfig was already stamped by the certificate renewer's sync before the backfill ran, which is why 2 of the 3 were stamped by the backfill.)

@braghettos
braghettos deleted the branch fix/serviceaccount-login-omit-kubeconfig October 29, 2026 14:48
@braghettos braghettos closed this Oct 29, 2026
Base automatically changed from fix/serviceaccount-login-omit-kubeconfig to main October 29, 2026 14:48
@braghettos

Copy link
Copy Markdown
Collaborator Author

Superseded by #44, the same branch rebased onto main. GitHub closed this one when its stacked base was deleted.

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.

Stamp identity facts (strategy, groups) on every <user>-clientconfig Secret

1 participant