Enterprise SSO (SAML / OIDC / LDAP)¶
Enterprise tier
SSO is an Enterprise feature. Enabling SSO requires an Enterprise license. Once configured, the login flow keeps authenticating users even if the license later lapses — a lapsed license must never lock existing SSO users out.
KubeManta authenticates operators through your own identity provider via three protocols on one pluggable engine, all configured through the same wizard:
- SAML 2.0 — Azure AD, Okta, Google Workspace, Cognito, Auth0, Ping, ADFS
- OIDC — authorization-code flow with PKCE against any standards-compliant provider (discovery-document based)
- LDAP / Active Directory — direct-bind over LDAPS or StartTLS
The local admin password is always retained as a break-glass path — an IdP outage can never lock you out of your own cluster.
How it works¶
One pipeline handles every protocol — the provider validates the login and produces an Identity, and everything downstream is shared:
flowchart LR
user["Operator<br/>(browser)"] -->|1. login| idp["Your IdP<br/>(SAML / OIDC / LDAP)"]
idp -->|2. validated identity| km["KubeManta Agent"]
km -->|3. validate + JIT provision| users[("user directory")]
km -->|4. group → role map| role{"admin?"}
role -->|5. issue session| user
- The operator signs in — a browser redirect to your IdP (SAML, SP-initiated; OIDC, authorization-code + PKCE) or a direct credential bind (LDAP).
- The provider returns a validated identity: a signed SAML assertion to the ACS endpoint, a verified OIDC ID token via the callback, or a successful LDAP bind plus attribute lookup.
- KubeManta just-in-time provisions the user, keyed on
(provider, subject)— no pre-creation required. - The IdP group claims are mapped to a KubeManta role (see below).
- KubeManta issues its normal signed session cookie. From that point the user is an ordinary authenticated session — session validation, admin gating, and RBAC are unchanged.
OIDC¶
The OIDC provider runs the authorization-code flow with PKCE. Endpoints are resolved from your issuer's discovery document (/.well-known/openid-configuration), the ID token's signature is verified against the issuer's JWKS (weak / none algorithms rejected before verification), and the state, nonce, and PKCE verifier are carried in a signed, short-lived state cookie. Outbound discovery/token/JWKS fetches are SSRF-guarded and DNS-rebind-pinned, with size caps and short timeouts.
LDAP¶
LDAP is a template direct-bind flow: the user binds with their own username + password — KubeManta stores no service-account bind credential. The connection must be ldaps:// or ldap:// + StartTLS (plaintext LDAP is refused — it would be a credential-capture vector); an optional PEM CA supports private/enterprise CAs. Empty passwords are rejected before any network bind (the LDAP "unauthenticated bind" bypass). After a successful bind, email and group memberships are read for JIT provisioning and role mapping. An insecure "skip TLS verification" toggle exists for development only and is clearly surfaced as unsafe.
JIT user provisioning¶
Users are created on first successful login, keyed on the identity provider plus the IdP's stable subject identifier. There is no separate "invite" or "create user" step. Deactivating a user is enforced per-request: a revoked SSO user is rejected within about 30 seconds. Password and API-key sessions carry no email claim and are unaffected.
Manage provisioned users in Admin → Auth (SSO).
Group → role mapping¶
KubeManta has two roles: admin and viewer. Mapping is intentionally simple:
- If any of the user's IdP group claims intersect the configured admin group(s) → the user is provisioned as admin.
- Otherwise → viewer (read-only).
Set the admin group(s) in the wizard. Everything downstream — write gating, Expert Mode, Resource Builder Apply — keys off this role exactly as it does for local accounts.
Break-glass local login¶
The sso.local_login policy controls how the local password login coexists with SSO:
| Value | Behavior |
|---|---|
all (default) |
Both SSO and local password login are available. |
admin_only |
The login page prefers SSO; local password login is restricted to the admin break-glass account. |
Local admin login is never fully disabled. km-reset-pw also always works from kubectl exec. Disabling SSO (which turns off enforcement entirely) is always available to an admin.
Assertion hardening¶
The SAML SP is configured for a modern security posture out of the box:
- RSA-SHA1 rejected. An RSA-SHA1-signed response is refused (per the OWASP SAML cheat-sheet).
- SHA-256 pinned. The SP-side signature and digest algorithms are pinned to SHA-256.
- Clock drift.
NotBefore/NotOnOrAfterare validated with a fixed 5-minute allowed clock drift. - Replay protection. Each assertion ID is recorded once and rejected on reuse.
InResponseTobinding. SP-initiated login binds each response to the request that started it, and requires the response'sInResponseToto match. A response with noInResponseTo(unsolicited / IdP-initiated) is rejected explicitly.- Signed AuthnRequests & encrypted assertions (optional). Generate an SP keypair from the admin wizard to turn on signed AuthnRequests and/or encrypted assertions for IdPs that require them.
- Single Logout. SP-initiated SLO is supported when your IdP advertises a SingleLogoutService URL; the SLO callback requires signed SLO messages — an unsigned LogoutRequest/LogoutResponse is rejected.
SP-initiated login only
SAML login is SP-initiated only (the user starts at KubeManta). Unsolicited / IdP-initiated responses are explicitly rejected via the InResponseTo binding above.
RelayState / CSRF¶
RelayState carries a signed CSRF nonce plus the return path in a short-lived, SameSite=Lax cookie. The return path is open-redirect-guarded to the same origin. The session cookie set after a successful SSO login uses SameSite=Lax so the fresh session survives the IdP's cross-site top-level redirect; local password login stays SameSite=Strict.
Integration endpoints¶
These are the public endpoints your IdP interacts with. The admin wizard shows you the exact URLs to register (ACS URL and SP Entity ID for SAML, redirect URI for OIDC).
| Endpoint | Purpose |
|---|---|
GET /auth/saml/login |
Start SP-initiated SAML login (redirect to IdP). |
POST /auth/saml/acs |
Assertion Consumer Service — receives the IdP's signed response. |
GET /auth/saml/metadata |
SP metadata XML for your IdP to consume. |
GET /auth/saml/logout |
Logout (starts SP-initiated SLO when the IdP advertises it; otherwise local). |
GET /auth/oidc/login |
Start the OIDC authorization-code + PKCE flow. |
GET /auth/oidc/callback |
OIDC redirect URI — code exchange + ID-token verification. |
POST /auth/ldap/login |
LDAP direct-bind login (username + password). |
Configuring, testing, and enabling SSO — and managing provisioned users — are all done from Admin → Auth (SSO) (admin-only). The audited actor for an SSO session is derived only from a cryptographically verified session, so a forged request on a public auth route cannot spoof the audited actor.
Admin wizard¶
Admin → Auth (SSO) is a guided setup:
- Pick the protocol (SAML / OIDC / LDAP) and an IdP preset.
- KubeManta shows the values your IdP needs — for SAML the ACS URL and SP Entity ID (metadata), for OIDC the redirect URI.
- Point at the IdP: upload/fetch SAML metadata, enter the OIDC issuer + client credentials, or the LDAP server URI + bind-DN template.
- Map the admin group(s) →
admin_groups. - Test the connection, then Enable.
The wizard's external base URL (the ACS / EntityID base, e.g. https://kubemanta.example.com) can be pre-filled from the Helm value sso.publicUrl — but the admin-entered configuration is always authoritative.
Configuration storage & audit¶
- The full SSO configuration is AES-256-GCM encrypted at rest, alongside your other stored credentials.
- SSO login, config changes, and user deactivation are all audited through the normal write-audit path. For SSO sessions the audited actor is email-aware (
email@ip).
Session revocation¶
Deactivating an SSO user takes effect within about 30 seconds cluster-wide: every request from an email-bearing session re-checks that the user is still active and rejects a revoked session inside that window.
Related¶
- Security Model — RBAC, roles, break-glass
- Access Control — IP allow/deny, idle timeout, exposure
- Free vs Pro vs Enterprise