Authentication
Modes
OIDC
Production. Sign-in delegated to your provider (Entra ID or any OIDC issuer).
AUTH_DISABLED
Development only. Injects a mock
dev@localhost admin and skips all token validation.The OIDC flow
The backend serves four auth endpoints:
The ID token is verified (signature + expiry) and the user’s email, name, and groups are read from it. The groups claim drives IAM membership.
Session cookie
On successful callback the backend issues an HS256-signed JWT stored in thek8s-gate-session cookie:
- HttpOnly, Secure, SameSite=Lax
- Claims:
email,name,groups, issuerk8s-gate, plus issued/expiry times - Lifetime from
SESSION_MAX_AGE(default86400= 24h)
Configuration
Authorization (IAM)
IAM is AWS-inspired: policies with Allow/Deny statements are attached to groups, groups map to your provider’s groups (or hold manual members), and every request is evaluated against the user’s effective policies. The mechanics — KRN matching, wildcard rules, unmapped routes, cache refresh — are covered in depth in Permissions model.Enforcement
When enforcing, a denied request returns403, and any route that isn’t mapped to a permission is denied by default.
KRN — resource names
Resources are addressed by KRN (krn:vks:...), built from type:id segments:
* matches one segment, a trailing * matches the rest, and prefixes like prod-* match prod-cluster-1.
Policy document
cluster:List), service (cluster:*), and full (*:*) wildcards. Every action Celum defines is listed in Permissions reference.
Evaluation order
1
Default deny
With no matching Allow, access is denied.
2
Explicit deny wins
Any matching
Deny statement immediately denies, overriding any Allow.3
Explicit allow
Otherwise, a matching
Allow grants access.Groups
A user’s groups come from two sources, combined:- Provider-mapped — a group whose
oidc_group_idmatches one of the user’s OIDC group/role claims (perOIDC_MAPPING_SOURCE). - Manual — emails added directly to a group.
The match on
oidc_group_id is exact, against whichever claim OIDC_MAPPING_SOURCE / OIDC_GROUPS_CLAIM selects. With OIDC_MAPPING_SOURCE=groups that means the provider’s group object ID, not its display name; with roles it means the app role’s value.Bootstrapping the first admin
A fresh database is seeded with anAdministrators group holding the K8sGateAdmin policy and mapped to the OIDC claim value krn:vks:admin. Without that seed, turning on IAM_ENABLED against an empty database locks everyone out — there would be policies, but no group carrying them and no claim mapping to anything, so every request ends in the default deny.
To get in, either assign the claim value krn:vks:admin to your account at the identity provider, or edit the Administrators group’s mapped OIDC group so it matches a claim you already carry.
Built-in policies
These are reconciled at startup and are read-only in the UI.Credential downloads are deliberately not in Operator or Viewer. Attach
K8sGateSensitiveRead separately to the people who should be able to pull a kubeconfig, talosconfig, or SSH password.Managing IAM in the UI
API clients can authenticate with a Bearer token issued from My permissions instead of the session cookie.
What commonly goes wrong
Next steps
Permissions model
How routes resolve to actions and KRNs, and how matching really works.
Permissions reference
Every action Celum defines, by service.
Architecture
Where session and IAM checks sit in the request pipeline.
Create a cluster
Cluster creation is gated by
cluster:Create.