Enterprise SSO
Analysts sign in with their corporate account: Caddy → oauth2-proxy → the IdP (Entra ID / Okta / Keycloak / AD). Roles map from IdP groups; audit traces to a person.
The default shape is the gateway's own password login plus the Users page. Companies with an IdP switch to docker-compose.sso.yml: accounts come from the IdP and the gateway no longer holds passwords. Do not run both.
Architecture
oauth2-proxy is a mature OIDC reverse proxy: unauthenticated requests are redirected to the IdP, and after login the verified identity is injected as request headers for the gateway. The gateway implements no login of its own and trusts only those headers. This is safe because the gateway is reachable only inside the proxy chain (every /api/* needs RST_GATEWAY_SHARED_SECRET) and oauth2-proxy overwrites the headers from its own session, so a client cannot forge them.
Protocol-agnostic: any front proxy that injects identity headers works, so SAML / LDAP fit too.
Connecting your IdP
Register an application
A confidential client with callback URI https://<hostname>/oauth2/callback. Note client_id, client_secret and the issuer URL.
Fill .env
OIDC_ISSUER_URL=https://login.microsoftonline.com/<tenant>/v2.0
OIDC_CLIENT_ID=<client id>
OIDC_CLIENT_SECRET=<client secret>
OAUTH2_PROXY_SKIP_OIDC_DISCOVERY=false
OAUTH2_PROXY_COOKIE_SECRET=<openssl rand -base64 32>
OAUTH2_PROXY_REDIRECT_URL=https://<hostname>/oauth2/callback
OAUTH2_PROXY_COOKIE_SECURE=true
OAUTH2_PROXY_REVERSE_PROXY=true
CADDY_SITE_ADDRESS=<hostname>
RST_GATEWAY_SHARED_SECRET=<openssl rand -hex 32>
RST_SSO_ENABLED=true
RST_SSO_ENFORCE=trueRole mapping
RST_RBAC_ADMIN_GROUPS=soc-admins
RST_RBAC_ANALYST_GROUPS=soc-l1,soc-l2
RST_RBAC_VIEWER_GROUPS=auditorsThe IdP's groups claim enters the identity; a person in several groups gets the highest tier. In none = no role (can write, cannot administer) - to enforce read-only, list the group in RST_RBAC_VIEWER_GROUPS.
Start
./deploy.sh and choose auth 2 = SSO; or by hand docker compose -f docker-compose.sso.yml up -d (without --profile bundled-idp).
Key variables
| Variable | Notes |
|---|---|
OIDC_ISSUER_URL / OIDC_CLIENT_ID / OIDC_CLIENT_SECRET | IdP issuer and client credentials |
OAUTH2_PROXY_SKIP_OIDC_DISCOVERY | false for a real IdP; true only for the bundled Keycloak demo |
OAUTH2_PROXY_COOKIE_SECRET | Session cookie encryption key |
OAUTH2_PROXY_REDIRECT_URL | Must match the IdP registration |
RST_SSO_ENABLED | Frontend shows the current user + sign-out |
RST_SSO_ENFORCE | true: gated /api/* without an identity gets 401; guards against a proxy that forgets to inject headers |
RST_SSO_USER_HEADER / RST_SSO_GROUPS_HEADER | Optional, override header names when using another front proxy |
Classic AD domains
Analysts sign in with AD / LDAP accounts: Keycloak does user federation against the directory, binds to LDAP at login, and issues OIDC to oauth2-proxy as usual. Microsoft AD specifics: vendor=ad, connectionUrl=ldaps://dc.corp.local:636, usernameLDAPAttribute=sAMAccountName, uuidLDAPAttribute=objectGUID, userObjectClasses=person, organizationalPerson, user, a service account as bindDn. Add a group-ldap-mapper to map AD security groups into the groups claim for role mapping.
Demo
The archive's docker-compose.sso.yml bundles a Keycloak + OpenLDAP (--profile bundled-idp) for demos: analyst / analyst123 (Keycloak local), analyst.ldap / Ldap123! (LDAP federation). Its realm is a starter template - client secret, redirectUris: ["*"], sslRequired: none are demo values; tighten them or use your own IdP before production.
How the gateway uses the identity
- Audit events carry the SSO identity in
user, traceable to a person. - The top-right corner shows the current user; sign-out goes through
/oauth2/sign_out. - The Account page cannot change the password; it lives in the IdP.
ES account permissions
A dedicated Elasticsearch account for the gateway: read on log indices, read / write on its own .rst_copilot_* indices, optionally read on alerts and osquery results. Kibana steps and the API version.
Upgrade, rollback and backup
Three ways to upgrade (re-run deploy.sh in place, online update, manual tag switch), health-gated rollback, the four things to back up, and the restore drill.