Skip to content

feat(auth): register hermes as an OIDC client - #49

Merged
ExtraToast merged 1 commit into
mainfrom
feat/hermes-oidc-client
Aug 29, 2026
Merged

ExtraToast merged 1 commit into
mainfrom
feat/hermes-oidc-client

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

Summary

Puts the Hermes dashboard behind estate single sign-on rather than its own password — the session that opens Grafana, Outline and Headlamp now opens Hermes.

  • buildHermesClient() — public client with PKCE, same shape as headlamp and rabbitmq.
  • Registered in AuthorizationServerConfig.
  • "hermes" to ServicePermission.HERMES in DOWNSTREAM_CLIENT_PERMISSIONS.

Public client is forced, not preferred. Hermes' dashboard exposes only HERMES_DASHBOARD_OIDC_ISSUER, _CLIENT_ID and _SCOPES — there is no client-secret field, so a confidential client could not authenticate. The upside is no Vault key and nothing to rotate.

The grant moves, it does not disappear. Hermes' route carries no forward-auth: a middleware there would intercept the OIDC callback and break the login before the dashboard sees the authorization code — the same reason outline is direct. So the HERMES grant is enforced at the authorize endpoint instead.

Validation

  • ./gradlew :api:test --tests '*RegisteredClientsTest*' --tests '*ServicePermissionTest*'36 tests, 36 passed.
  • The new test pins both redirect URIs, because that string is coupled to HERMES_DASHBOARD_PUBLIC_URL in fleet-infra: Hermes builds the callback as <public_url>/auth/callback verbatim, and a drift fails at the redirect with only a generic error surfaced.

Risk

  • Additive. A new registered client cannot change how an existing one resolves, and hermes collides with no existing client id.
  • No secret introduced anywhere — no Vault path, no Kubernetes Secret, no bootstrap step.
  • Grant sparingly. The dashboard is a control plane for an agent that executes shell commands; the grant is closer to DASHBOARD than to a media app. ADMIN bypasses as usual.
  • Companion fleet-infra change removes forward-auth from the route. Landing this first is harmless (the client simply goes unused); landing the fleet-infra side first would leave the dashboard with no working auth provider.

Links

  • Companion: JorisJonkers-dev/fleet-infra — OIDC env, forward-auth removal, and the Vault secrets script.

Puts the Hermes dashboard behind estate single sign-on instead of its own
password: the session that opens Grafana, Outline and Headlamp now opens
Hermes too.

Public client with PKCE, the same shape as headlamp and rabbitmq. That is
forced rather than chosen -- Hermes' dashboard takes only
HERMES_DASHBOARD_OIDC_ISSUER, _CLIENT_ID and _SCOPES, with no field for a
client secret, so a confidential client could not authenticate at all. The
upside is there is no secret in Vault and none to rotate.

The HERMES grant moves rather than disappears. Hermes' route carries no
forward-auth -- a middleware there would intercept the OIDC callback and
break the login before the dashboard sees the authorization code, which is
why outline is `direct` too -- so DOWNSTREAM_CLIENT_PERMISSIONS enforces
the grant at the authorize endpoint instead.

The redirect URIs are the one coupling worth watching: Hermes builds its
callback as <public_url>/auth/callback verbatim from
HERMES_DASHBOARD_PUBLIC_URL in fleet-infra. If the two drift the flow fails
at the redirect and the dashboard reports only a generic error, so the test
pins both spellings.
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: auth Authentication, authorization, sessions, or identity. component: security Security, permissions, secrets, or vulnerability handling. priority: P2 Medium; normal planned work. labels Aug 29, 2026
@ExtraToast
ExtraToast merged commit 6275e33 into main Aug 29, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth Authentication, authorization, sessions, or identity. component: security Security, permissions, secrets, or vulnerability handling. priority: P2 Medium; normal planned work. type: feature New user-facing or operator-facing capability.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant