The README was 1,240 lines of reference material and still described a SQLite quick start. It is now a short tour (highlights, screenshots of the web UI, an accurate quick start against Postgres), and each topic has its own page under docs/ with an index: deployment, configuration, Alertmanager, incidents, notifications, escalation, dead man's switches, single sign-on, web UI, API and development. SERVICE-ACCOUNTS.md is rewritten from a proposal into a reference, and TEAM-LOOKUP.md is gone with the endpoint it described. The "Upgrading to ..." sections for an unreleased product are dropped. Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
6.1 KiB
Single sign-on (OIDC)
Signing in through an OpenID Connect provider, and mapping its groups to teams and administrators. Back to the README and the documentation index.
terdut can sign people in through any OpenID Connect provider; the examples use Authentik. Groups at the provider decide who may sign in, which teams they belong to and whether they administer the install, much as Grafana's OAuth role and org mapping does. Password login keeps working alongside it unless you turn it off.
At the provider, create an OAuth2/OpenID provider and an application for it:
a confidential client, redirect URI <TERDUT_PUBLIC_URL>/api/oidc/callback, and
the openid, profile and email scopes. The issuer is the application's, e.g.
https://auth.example.com/application/o/terdut/. Then set:
TERDUT_PUBLIC_URL=https://terdut.example.com
TERDUT_OIDC_ISSUER=https://auth.example.com/application/o/terdut/
TERDUT_OIDC_CLIENT_ID=terdut
TERDUT_OIDC_CLIENT_SECRET=...
TERDUT_OIDC_ALLOWED_GROUPS=terdut-users,terdut-admins
TERDUT_OIDC_ADMIN_GROUP=terdut-admins
Which team a group grants is not server-wide config: each team names its own
group(s), set by that team's own owner (or an administrator) from its Members
tab, or PUT /api/teams/{teamID}/oidc-groups {"member_group":"sre","owner_group":"sre-leads"}.
A team must already exist before a group can grant access to it — the sync
never creates one.
The web UI's sign-in page shows a "Sign in with " button (a plain link to
/api/oidc/login) above the password form, or instead of it when
TERDUT_PASSWORD_LOGIN=false; it asks GET /api/auth/config what the server offers
(password_login, oidc.enabled, oidc.name). A refused sign-in comes back to that
page with the reason spelled out. Access the groups grant is badged SSO on the
Team, Admin and per-user pages, with its edit and remove controls disabled, and the
Account page does not offer to set a password nobody could use.
What a sign-in does
- Who. The provider's
(issuer, subject)is the identity. The first time, a user is found by email — only when the provider marks it verified, orTERDUT_OIDC_TRUST_EMAILis set — or created with no password. A username taken by somebody else gets a numeric suffix (alice-2). Username and email follow the provider at each sign-in. Authentik reportsemail_verifiedas false unless configured otherwise, so linking existing users usually needsTERDUT_OIDC_TRUST_EMAIL=true. - Whether. With
TERDUT_OIDC_ALLOWED_GROUPSset, somebody in none of them is refused and nothing is created. - What. The administrator flag follows
TERDUT_OIDC_ADMIN_GROUP. Team roles follow each team's ownoidc_member_group/oidc_owner_group; where both of a team's groups match, the owner group wins.
Managed access. What the sync grants is marked as managed by single sign-on,
and only that is ever changed by it. It is added at sign-in, and removed at the
next sign-in after the group is gone, even if that leaves a team without an owner
(an administrator can always repair a team) — the provider is the source of truth
for what it grants, so the last-owner and last-administrator guards do not apply.
Memberships and administrators added by hand are left alone; the exception is a
hand-added member whose team's own group grants a higher role, who is raised and
from then on managed. Editing managed access by hand (POST or DELETE on a
team's members, revoking an SSO-granted administrator) is refused with 409, since
the next sign-in would undo it.
Upgrading past migration 013: reconfigure every team's groups.
TERDUT_OIDC_GROUP_MAPPINGSis gone, and the sync no longer creates a team by name. Group-to-team-role mapping is now each team's own setting — an owner sets it from the Members tab, orPUT /api/teams/{teamID}/oidc-groups. Until a team's owner does that, an OIDC-sourced membership in it is dropped at that user's next SSO sign-in, the same as any other loss of group access. Set every team's groups before affected users next sign in, to avoid a visible gap in access.
How fast changes arrive. Groups are read only at sign-in. A session made by an
SSO sign-in has a hard ceiling (TERDUT_OIDC_SESSION_MAX_AGE, default 12h) that
sliding never extends, so a change at the provider reaches terdut within that time.
Password sessions are unaffected.
API keys are not revoked when somebody is removed at the provider. terdut holds no refresh token and never asks the provider again, so a person removed from every allowed group loses their sessions within
TERDUT_OIDC_SESSION_MAX_AGEand cannot sign in again, but keeps any API key they made (the TUI and scripts use them) until an administrator disables the user in terdut.
Signing in from a terminal. A client with no browser of its own, such as the TUI over SSH, signs in with a device code, run by terdut itself so the terminal never talks to the provider:
- The terminal calls
POST /api/oidc/deviceand shows the person a link (<TERDUT_PUBLIC_URL>/device?code=XXXX-XXXX) and the code. - On any device the person opens the link, signs in (by the provider or by password, whatever the login page offers), sees the code and the account, and presses Approve. Only a browser session can approve; an API key cannot.
- The terminal polls
POST /api/oidc/device/tokenevery 5 seconds and is given the ordinaryterdut_sessioncookie once. A person who signs in through the provider gets the sameTERDUT_OIDC_SESSION_MAX_AGEceiling on the terminal's session as on their browser's.
A login expires after 10 minutes. GET /api/auth/config reports device_login.
If the provider is down, terdut still starts (discovery is fetched on first
use) and password login is the way in. With TERDUT_PASSWORD_LOGIN=false that way
is closed: set it back to true. The first administrator comes from the bootstrap
endpoint, and stays a manual administrator that no group can revoke; on an SSO-only
install set bootstrap.enabled: false in the chart if you don't want that account,
or keep it and never give it a password.