Skip to content

feat: configure login parameters and expose Kubernetes identity - #37

Merged
sunib merged 4 commits into
feat/encrypted-cookie-sessionsfrom
feat/configurable-login-identity
Oct 5, 2026
Merged

sunib merged 4 commits into
feat/encrypted-cookie-sessionsfrom
feat/configurable-login-identity

Conversation

@sunib

@sunib sunib commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

PR 2 of the audience release plan. It is stacked on #36; rebase it onto main once #36 merges.

  • Login parameters: -login-config-file (chart: login) names the issuer's extra authorization parameters, each with a default, allowFromRequest and allowedValues. Links pass values as oidc.<name>. Anything else, including state, nonce, PKCE, client, redirect URI, scope, request and credential parameters, gets 400 login-parameter-refused before a login starts. Values are never logged or echoed.
  • Session claims: /auth/session adds displayName, groups and an optional connector, read through JSON Pointers into the verified token, always in a fixed shape.
  • /auth/whoami: a SelfSubjectReview with the user's token through the gate, sharing one implementation with the shared watches' reviews. Refusals pass through; failures and redirects give 503.
  • Attribution: the e2e API server maps name and email to configbutler.ai/claims/display-name and configbutler.ai/claims/email. Specs check both in whoami, the audit event, and an admission request captured with a ValidatingAdmissionPolicy in Warn mode, while the browser sends spoofed identity headers.
  • The browser helper gains login(returnTo, params) and loginURL().

Unit tests, lint and a mutation check of the parameter boundary pass. task verify is green locally, including the new e2e specs, on a fresh fixture. A reused fixture loses its Dex and test-issuer host aliases when the authentication config changes and the API server restarts; that is a fixture limitation, and CI always starts fresh.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added configurable sign-in parameters, including defaults, approved request values, and retry-link behavior.
    • Added configurable session identity claims and a /auth/whoami endpoint that reports the identity resolved by the Kubernetes API server.
    • Added browser helpers for building sign-in links with issuer-specific parameters.
    • Added Helm chart options for configuring sign-in parameters and session claims.
  • Documentation
    • Expanded setup and API documentation for sign-in parameters, session claims, and identity lookup.

- Login parameters: -login-config-file (chart: login) names extra query
  parameters for the issuer's authorization endpoint by the issuer's own
  names, each with a default, allowFromRequest and allowedValues. A login link
  gives values as oidc.<name>. Anything else, krm-foyer's own parameters
  (state, nonce, PKCE, client, redirect URI, scope, request, credentials)
  included, is a 400 login-parameter-refused before a login starts, with the
  value neither shown nor logged. Values are encoded once and never changed.
  A failed login's retry link repeats listed choices only, never a free hint.
- Session claims: /auth/session adds displayName, groups and an optional
  connector, from JSON Pointers into the verified ID token, in a fixed shape;
  a claim of the wrong type fails the login as session-claims-invalid.
- /auth/whoami: a SelfSubjectReview with the user's own token through the
  gate, sharing one implementation with the shared watches' reviews. Refusals
  pass through; failures, empty answers and redirects are 503s.
- Attribution: the e2e API server maps name and email to the two user.extra
  keys gitops-reverser reads; specs check them in /auth/whoami, the audit
  event and an admission request, with spoofed identity headers.
- The browser helper's login() takes parameters, and loginURL() builds the
  same link for an anchor or a QR code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1a26c8ca-e8f1-43ce-8d08-5825349cf003
📥 Commits

Reviewing files that changed from the base of the PR and between bcf73ff and b9b13ad.

📒 Files selected for processing (37)
  • README.md
  • charts/krm-foyer/README.md
  • charts/krm-foyer/templates/_helpers.tpl
  • charts/krm-foyer/templates/deployment.yaml
  • charts/krm-foyer/templates/login.yaml
  • charts/krm-foyer/values.schema.json
  • charts/krm-foyer/values.yaml
  • cmd/krm-foyer/chart_test.go
  • cmd/krm-foyer/main.go
  • cmd/krm-foyer/main_test.go
  • docs/design.md
  • docs/frontend.md
  • docs/investigations/audience-release-plan.md
  • docs/roadmap.md
  • docs/testing.md
  • internal/auth/auth.go
  • internal/auth/auth_test.go
  • internal/auth/claims.go
  • internal/auth/issuer_test.go
  • internal/auth/login_config.go
  • internal/auth/login_config_test.go
  • internal/auth/transactions.go
  • internal/gate/gate.go
  • internal/pages/assets/foyer.js
  • internal/pages/foyer.test.js
  • internal/proxy/lifecycle_test.go
  • internal/server/server.go
  • internal/server/server_test.go
  • internal/stream/shared.go
  • internal/stream/shared_test.go
  • internal/stream/stream_test.go
  • internal/stream/whoami.go
  • internal/stream/whoami_test.go
  • test/e2e/cluster/authentication-config.yaml
  • test/e2e/cluster/foyer-values.yaml
  • test/e2e/fixture_test.go
  • test/e2e/foyer_identity_test.go

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The pull request adds configurable issuer login parameters and ID-token session claims. It also implements /auth/whoami using a Kubernetes SelfSubjectReview, adds chart and browser-helper support, and extends unit and end-to-end coverage for login behavior and identity attribution.

Changes

Login and identity

Layer / File(s) Summary
Configure login parameters
charts/krm-foyer/*, cmd/krm-foyer/*, internal/pages/assets/foyer.js, internal/pages/foyer.test.js, README.md
The Helm chart and command-line parser accept authorization-parameter and session-claim configuration. The browser helper adds loginURL() and accepts issuer parameters under oidc.<name>.
Process login parameters and session claims
internal/auth/*, docs/design.md, docs/investigations/audience-release-plan.md
Login validates supplied parameters, forwards configured defaults and accepted overrides, and preserves only allowed values in retry links. Transactions reject cookies over the configured size limit. Session claims are extracted from the verified ID token.
Resolve Kubernetes identity
internal/server/*, internal/stream/*, internal/gate/gate.go, cmd/krm-foyer/main.go, docs/design.md, docs/frontend.md
The server routes /auth/whoami to a handler that submits a SelfSubjectReview with the admitted session token. The response includes Kubernetes UserInfo, session issuer, and expiry.
Verify identity attribution
test/e2e/*, docs/testing.md, docs/roadmap.md
End-to-end fixtures configure signed claim mappings and login options. Tests check session claims, /auth/whoami, and signed identity data in admission warnings and audit events.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant WhoAmI as Streams.WhoAmI
  participant Gate
  participant API as Kubernetes API server
  Browser->>WhoAmI: GET /auth/whoami
  WhoAmI->>Gate: Admit request
  Gate-->>WhoAmI: Session credential
  WhoAmI->>API: SelfSubjectReview with session token
  API-->>WhoAmI: UserInfo or API error
  WhoAmI-->>Browser: Identity response or error status
Loading

Merge Risk: ⚪ Minimal · up to b9b13

No actionable merge-blocking issue is established; the PR is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b9b13

The inspected changes keep login options under deployment control and resolve Kubernetes identity using the signed-in user's token. No introduced privilege escalation or identity substitution was established. Remaining uncertainty concerns deployment-specific identity policies and compatibility outside the repository.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The new public exposure is a session-authenticated lookup of the caller's identity at the configured Kubernetes API server. Requests cannot select another destination or gain the pod's service-account authority. Login-option delegation is limited to names and values permitted by deployment configuration.

Trust Boundaries and Controls

  • observed — The upstream client is constructed from the admitted session bearer token rather than request Authorization, Impersonate-, or X-Remote- headers. Inspected tests explicitly assert header-spoofing isolation, no-session refusal, no token in successful responses, and redirect refusal without contacting the redirect target.

Resilience and Maintainability Implications

  • observed — Transaction cleanup is response-cookie deletion, not atomic server-side consumption: concurrent callbacks can decrypt the same live transaction. This behavior predates the PR. State, nonce, and PKCE bindings remain, so it is an existing lifecycle limitation rather than an introduced architecture concern. The new cookie-size check rejects oversized transactions before emitting their cookie.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 54 functions across 23 files. (14 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: configurable login parameters and exposure of Kubernetes identity.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 74.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 54 functions across 23 files. (14 skipped: 14 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

sunib and others added 2 commits October 5, 2026 15:34
Accepted login parameters and a long return path could seal into a login
cookie over 4,096 bytes once JSON-escaped, encrypted and base64-encoded; the
browser dropped it and the login failed at its callback. begin now checks the
cookie's name and value against 4,000 bytes and the login answers 400
login-too-large before reaching the issuer.

Also corrects two docs: the roadmap no longer asks for shared session
storage, and the plan says the plaintext token goes to the API server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…end them

The gate fails closed: a session check that does not answer within one
interval counts as an ended session. Every stream test ran with a 20ms
interval, so on a loaded CI runner a check that would have answered was
sometimes not scheduled in time, and a stream was cut short
("session_ended" in its log) before its first event. Reproduced locally
with 12 copies of the test binary at once, on this branch and on the one
below it.

The stream tests now keep the gate's default interval, as the proxy tests
already do, and the two that end a session opt into the short one.
TestACredentialWithoutLiveIsCutShort accepts the abort before the
response head that its first check can cause, as endsAborted does for
the other cut-short tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sunib
sunib merged commit f98a49e into main Oct 5, 2026
11 checks passed
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