Skip to content

Add OIDC authentication and Kubernetes RBAC to Console - #1787

Merged
gjkim42 merged 1 commit into
mainfrom
feat/console-oidc
Oct 1, 2026
Merged

gjkim42 merged 1 commit into
mainfrom
feat/console-oidc

Conversation

@gjkim42

@gjkim42 gjkim42 commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

What type of PR is this?

/kind feature

What this PR does / why we need it:

The shared Console token gives every holder the server ServiceAccount's authority. Add opt-in OIDC authentication through an OAuth2 Proxy sidecar and per-user Kubernetes SubjectAccessReview checks, so operators can grant Console access through namespace RoleBindings.

  • Keep static-token authentication as the default, with no CRD changes.
  • Bind Kelos to loopback in OIDC mode and expose only the proxy. Require HTTPS, secure cookies, explicit identity prefixes, and trusted proxy addresses; strip caller identity and credential headers.
  • Authorize resource reads, Session edits and lifecycle actions, Task logs, attachments, and every chat/terminal connection before accessing downstream resources. Filter inventory and relationships by the resource kinds the caller may list.
  • Provide an unbound Console user ClusterRole, structured authorization audit events, signed-in identity display, logout, and configuration/RBAC documentation.

Which issue(s) this PR is related to:

Fixes #1450

Special notes for your reviewer:

No users receive permissions automatically. Operators must configure an OIDC client, HTTPS ingress, an existing Secret, and namespace RoleBindings. sessions/connect grants full interactive chat and shell access; general Session patch permissions also allow lifecycle changes. Existing WebSockets retain access until disconnected. New requests and connections perform fresh authorization checks, while IdP changes remain subject to proxy refresh/expiry.

Validation:

  • make test TEST_FLAGS='-count=1 -run=TestConsoleBrowserAuthentication' passed with workspace token/Codex environment variables removed. The browser identity test requires exactly one request to /api/config.
  • env -u CODEX_AUTH_JSON -u CODEX_HOME make test passed. The two variables were removed only from the test process because inherited workspace configuration affects existing entrypoint tests.
  • make test-integration TEST_FLAGS='-count=1 -run=TestConsoleOIDC' passed using the rendered configuration, the real OAuth2 Proxy binary, a local test issuer, and an envtest Kubernetes API server with RBAC. Covers two identities, namespace isolation, forged headers, inventory relationships, suspend/resume, WebSocket upgrades/reconnects, revocation, and logout. Envtest has no kubelet; successful stream operations, attachment transfers, and Task logs are covered with unit-test fakes.
  • make verify, make build WHAT=cmd/kelos-console-server, and git diff --check passed.
  • Local race testing could not run because this container lacks a C compiler. The integration CI job runs with -race. Cluster e2e validation is left to PR CI.

UI comparison: the same 1280×900 Settings view and empty namespace fixture, rendered from the base and PR frontend assets. The after image supplies the OIDC username through the config API fixture; these screenshots illustrate the UI, not a live IdP deployment.

Before — shared-token mode

Before: Settings without an individual identity

After — OIDC mode

After: Settings shows the signed-in OIDC identity

Does this PR introduce a user-facing change?

Kelos Console supports opt-in OIDC sign-in through OAuth2 Proxy and per-user Kubernetes RBAC authorization using namespace RoleBindings. Static-token authentication remains the default. OIDC setup requires HTTPS, an identity-provider client, an existing Secret, and explicit access grants.

Summary by cubic

Adds opt-in OIDC authentication to the Console through an OAuth2 Proxy sidecar, with per-user Kubernetes RBAC authorization. Static-token authentication remains the default.

New Features

  • OIDC mode binds the server to loopback, exposes only the proxy, and requires HTTPS, secure cookies, identity prefixes, and trusted proxy IPs; caller identity and credential headers are stripped.
  • Authorizes every read, Session edit, lifecycle action, attachment transfer, Task log, and chat or terminal connection per user, and filters inventory and relationship listings to resource kinds the caller may list.
  • Adds a ClusterRole for Console users, structured authorization audit events, signed-in identity display, and logout, and removes kelos-console-user on uninstall.
  • Provides integration coverage with the real OAuth2 Proxy binary, a local test issuer, and an envtest API server with RBAC.

Migration

  • Adopting OIDC requires an identity-provider client, HTTPS ingress, an existing Secret, and namespace RoleBindings; no users receive permissions automatically.
  • Existing WebSockets keep their access until disconnected, while new requests and connections are checked fresh.

Fixes #1450.

Written for commit ec082a0. Summary will update on new commits.

Review in cubic

@gjkim42 gjkim42 added the kind/feature Categorizes issue or PR as related to a new feature label Oct 1, 2026
@gjkim42

gjkim42 commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator Author

/kelos review

@kelos-bot

kelos-bot Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Kelos Task Status

Task kelos-reviewer-issue-comment-a53ec80c8c4e has succeeded. ✅

@kelos-bot

kelos-bot Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

🤖 Kelos Reviewer Agent @gjkim42

Review Summary

Verdict: APPROVE
Overall correctness: patch is correct
Scope: Adds an opt-in OIDC mode to the Console. An OAuth2 Proxy sidecar authenticates users, Kelos listens only on loopback and accepts identity headers only from loopback, and each API and WebSocket operation is checked with a SubjectAccessReview. Static-token mode stays the default.

Findings Overview

Priority Count File:Line Summary
P0 0 — none
P1 0 — none
P2 1 internal/manifests/charts/kelos/README.md:258 openssl rand -base64 32 cookie secret is rejected by OAuth2 Proxy about 73% of the time
P3 1 internal/consoleserver/auth.go:126 Exact-string Origin match breaks writes and WebSockets when the redirect host has uppercase letters or an explicit :443

Findings

Documentation accuracy

  • [P2] internal/manifests/charts/kelos/README.md:258-259 — The README says to generate the cookie secret with openssl rand -base64 32. That command prints standard base64. OAuth2 Proxy v7.15.5 decodes the secret only as URL-safe base64 (encryption.SecretBytes uses base64.RawURLEncoding). If decoding fails, it uses the raw 44-character string, and validateCookieSecret then fails with cookie_secret must be 16, 24, or 32 bytes ... but is 44 bytes. About 73% of 32-byte secrets contain + or / in standard base64. For those, the oauth2-proxy container goes into CrashLoopBackOff on the first OIDC rollout. Because the Kelos container's probes go through port 4180, the Console pod never becomes Ready. The upstream docs use openssl rand -base64 32 | tr -- '+/' '-_'. Use that command and say "URL-safe base64". The integration test misses this because its fixed secret (bytes.Repeat([]byte{42}, 32)) encodes without + or /.

Correctness

  • [P3] internal/consoleserver/auth.go:126 (also CheckOrigin in server.go and --external-url at templates/console-server.yaml:59) — The chart builds --external-url as https:// plus (urlParse $oidc.redirectURL).host, keeping the host's case and port. validateAuth accepts values like https://Console.Example.com or https://console.example.com:443. Browsers lowercase the host and drop the default port when they send Origin, so origins[0] != s.oidc.ExternalURL fails. Reads keep working, but every POST, PATCH, DELETE and chat or terminal WebSocket returns 403 request origin is not allowed. To fix this, either normalize the origin in validateAuth (lowercase the host, drop :443) and compare against the normalized value, or reject such values in both the chart and validateAuth.

Suggestions (optional)

  • [P3] internal/manifests/charts/kelos/templates/console-server.yaml:46,103 — The new oauth2-proxy sidecar gets the kelos-console-server ServiceAccount token, because the token is mounted into every container by default. That ServiceAccount can create pods/exec and Sessions across the cluster. The proxy is the only container that handles unauthenticated internet traffic. For defense in depth, set automountServiceAccountToken: false on the pod and mount a projected serviceAccountToken volume only in the console-server container.
  • [P3] Makefile:53,166 — make test-integration now depends on oauth2-proxy, which runs gh release download and sha256sum. Every local integration run, not just make test-oidc, now needs an installed and authenticated gh. CONTRIBUTING.md doesn't mention this. The release assets are public, so curl -fsSL https://github.com/oauth2-proxy/oauth2-proxy/releases/download/... would avoid the auth requirement. Otherwise, document the requirement next to make test-integration.

Key takeaways

  • The authorization checks are complete. Every route in api() that reads or changes Kelos resources, Pod logs, attachments, or chat/terminal streams runs requireAccess before any client call. The unit tests check, for each endpoint, that a denied, failed, or erroring SubjectAccessReview stops the request before any Kubernetes access. The tests with the real proxy and envtest RBAC cover forged headers, namespace isolation, revocation, and reconnects.
  • Static-token mode is unchanged: allowed() returns early when s.oidc == nil, and the /api/config and logout responses are unchanged for that mode.
  • Fix the cookie-secret command before release. Most operators following the README will hit a crash-looping proxy.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 28 files

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread internal/consoleserver/auth.go Outdated
Comment thread docs/reference.md
Comment thread .github/workflows/ci.yaml
Comment thread internal/manifests/charts/kelos/templates/console-server.yaml
Comment thread internal/consoleserver/web/app.js Outdated
Comment thread internal/consoleserver/testdata/authentication_test.js Outdated
Comment thread internal/manifests/charts/kelos/values.schema.json
Comment thread cmd/kelos-console-server/main_test.go Outdated
Comment thread internal/helmchart/console_oidc_test.go Outdated
Comment thread Makefile Outdated
@gjkim42
gjkim42 force-pushed the feat/console-oidc branch from 92ac19d to ddc603d Compare October 1, 2026 14:46
@gjkim42

gjkim42 commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the Kelos reviewer findings in ddc603d: the cookie-secret instructions now use URL-safe base64, the real-proxy test exercises URL-safe characters, and configured origins are normalized for uppercase hosts and explicit HTTPS ports. The optional credential-mount and contributor-prerequisite findings are also addressed.

The valid inline findings are fixed or clarified, including the reserved-prefix bypass. The subject-claim report was verified against the pinned upstream source and existing integration assertion; the schema-placement suggestion retains the existing pre-deployment render checks. Explanations are recorded in those threads.

The PR is squashed to one commit and pushed with --force-with-lease. Unit tests, the OIDC integration test, generation/format/vet verification, the Console build, and a fresh proxy download/checksum check passed. CI is rerunning for the updated head.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 15 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread internal/consoleserver/testdata/authentication_test.js Outdated
Comment thread .github/workflows/ci.yaml
@gjkim42
gjkim42 force-pushed the feat/console-oidc branch from ddc603d to b076a91 Compare October 1, 2026 21:29
@gjkim42
gjkim42 added this pull request to the merge queue Oct 1, 2026
@gjkim42
gjkim42 removed this pull request from the merge queue due to a manual request Oct 1, 2026
@gjkim42
gjkim42 added this pull request to the merge queue Oct 1, 2026
@gjkim42
gjkim42 removed this pull request from the merge queue due to a manual request Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature needs-actor needs-priority needs-triage release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[kelos-fake-strategist] Integration: Add OIDC and Kubernetes RBAC delegation for safe shared Console access

1 participant