Skip to navigation

Access Control

View as Markdown

The OpenShell gateway supports these access-control models for human callers on Kubernetes:

ModelWhen to use
mTLSGateways with a configured client CA and no OIDC issuer. The gateway maps a verified client certificate to a user identity.
OIDC (recommended)Production deployments. Integrates with an existing identity provider, supports role-based access control, and gives each user their own identity without distributing certificates.
Reverse-proxy auth terminationAn access proxy (Cloudflare Access, ngrok, corporate SSO) authenticates callers in front of the gateway. The gateway trusts the proxy and skips its own client-cert check.

The Helm chart generates a gateway TLS certificate and a user client certificate at install time. Supervisor Pods project only ca.crt from the client Secret so they can authenticate the gateway; the client certificate and private key are not exposed to sandboxes. Supervisors authenticate their RPCs with gateway-minted sandbox JWTs.

For how the CLI resolves gateways and stores credentials, refer to Gateway Authentication.

Sandbox Supervisor Identity

Kubernetes sandbox supervisors use gateway-issued session JWTs for sandbox-specific RPCs. A dedicated supervisor reads its preissued credential bundle from a mounted Secret. A shared supervisor receives each sandbox’s bundle through its assignment stream, authenticated with a separate supervisor-host JWT. See Getting the first credential.

The separate IssueSandboxToken bootstrap exchange remains available. When used, the Kubernetes driver validates the projected ServiceAccount token and returns the authenticated sandbox ID and runtime identity. The gateway requires the driver and runtime identity to match its stored sandbox record before issuing a gateway JWT.

Dynamic provider token grants can use SPIFFE without changing supervisor-to-gateway authentication. Set gatewayConfig.openshell.drivers.kubernetes.provider_spiffe_workload_api_socket_path to mount the SPIFFE CSI Workload API socket into gateway and sandbox pods while keeping gateway-issued session JWTs for sandbox-specific RPCs.

Provider token grants require a SPIFFE implementation such as SPIRE and identities for the gateway and sandbox pods. The repository’s local SPIRE overlay assigns sandbox IDs from the pod’s openshell.ai/sandbox-id annotation, but the gateway validation path only requires the supervisor SVID to be valid and in the same SPIFFE trust domain as the gateway SVID. Provider profiles with token_grant metadata cause the sandbox supervisor to request JWT-SVIDs and exchange them for upstream OAuth2 access tokens. Token-exchange profiles also require a gateway SPIFFE identity because the gateway brokers the intermediate token exchange with its own JWT-SVID.

The gateway verifies supervisor JWT-SVIDs with JWT bundles fetched from the SPIFFE Workload API, so intermediate token exchange does not require gateway access to the SPIRE OIDC discovery endpoint or its TLS CA.

OIDC User Authentication

Set gatewayConfig.openshell.gateway.oidc.issuer to enable OIDC. The gateway validates the Authorization: Bearer <token> header on every request against the issuer’s JWKS endpoint. It accepts JWTs signed with RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, or EdDSA (Ed25519) keys published in the issuer JWKS. Okta tenants that sign access tokens with ES256 work without additional gateway configuration.

helm upgrade openshell \
oci://ghcr.io/nvidia/openshell/helm-chart \
--version <version> \
--namespace openshell \
--set 'gatewayConfig.openshell\.gateway\.oidc.issuer=https://your-idp.example.com/realms/openshell' \
--set 'gatewayConfig.openshell\.gateway\.oidc.audience=openshell-cli' \
--set server.tls.clientCaSecretName=""

Client certificates are optional at the TLS handshake, so OIDC callers can connect without them. Set server.tls.clientCaSecretName="" to disable client-certificate verification entirely. The chart omits client_ca_path from gateway.toml and does not mount the client-CA volume, leaving HTTPS-only transport with OIDC for user authentication. Do not set the value to null; omit the key to use the chart default, or set it to "" to disable client certificate verification.

The audience value must match the client ID configured in your identity provider for the OpenShell resource server.

OIDC values reference

ValueDefaultPurpose
gatewayConfig.openshell.gateway.oidc.issuer""OIDC issuer URL. Empty disables OIDC.
gatewayConfig.openshell.gateway.oidc.audienceopenshell-cliExpected aud claim in the JWT.
gatewayConfig.openshell.gateway.oidc.jwks_ttl_secs3600JWKS key cache TTL in seconds. Must be greater than zero.
gatewayConfig.openshell.gateway.oidc.roles_claimrealm_access.rolesDot-separated path to the roles array in JWT claims.
gatewayConfig.openshell.gateway.oidc.admin_roleopenshell-adminRole name that grants admin access.
gatewayConfig.openshell.gateway.oidc.user_roleopenshell-userRole name that grants standard user access.
gatewayConfig.openshell.gateway.oidc.scopes_claim""Dot-separated path to the scopes array in JWT claims.

The issuer must use HTTPS. The gateway rejects discovery and JWKS redirects, limits response sizes, requires a JSON media type, and rejects a jwks_uri on a different origin unless that origin appears in jwks_allowed_origins. Use server.oidc.caConfigMapName for issuers signed by a private CA.

Auth-only mode vs. RBAC mode

When OIDC is enabled, omitting the role fields uses the defaults above and enables RBAC. To use auth-only mode, explicitly set both admin_role and user_role to empty strings ("") under gatewayConfig.openshell.gateway.oidc. Authenticated users are treated as Platform Admins and bypass workspace membership checks. Configured OAuth scope checks still apply.

Keep the default role names, or configure both names for your identity provider, to use RBAC mode. The gateway checks the role claim and enforces access based on the assigned role:

helm upgrade openshell \
oci://ghcr.io/nvidia/openshell/helm-chart \
--version <version> \
--namespace openshell \
--set 'gatewayConfig.openshell\.gateway\.oidc.issuer=https://your-idp.example.com/realms/openshell' \
--set 'gatewayConfig.openshell\.gateway\.oidc.audience=openshell-cli' \
--set server.tls.clientCaSecretName="" \
--set 'gatewayConfig.openshell\.gateway\.oidc.roles_claim=realm_access.roles' \
--set 'gatewayConfig.openshell\.gateway\.oidc.admin_role=openshell-admin' \
--set 'gatewayConfig.openshell\.gateway\.oidc.user_role=openshell-user'

The effective role names must either both be non-empty or both be empty. The gateway rejects a configuration with exactly one empty role name.

OIDC RBAC combines method-level role and optional scope checks with workspace membership and role checks. Sandboxes and providers belong to a workspace, rather than to individual OIDC subjects. Workspace Users can use sandboxes and attach providers within their assigned workspaces; Workspace Admins manage resources in those workspaces. Platform Admins bypass workspace membership checks. Configure OIDC roles and separate workspace memberships when users must not access each other’s resources. See Workspaces.

Provider-specific rolesClaim paths

ProviderrolesClaim value
Keycloakrealm_access.roles
Microsoft Entra IDroles
Oktagroups

Reverse-Proxy Auth Termination

When an access proxy, such as Cloudflare Access, ngrok, or a corporate SSO gateway, terminates TLS and handles authentication in front of the OpenShell gateway, configure the gateway for plaintext traffic from that trusted proxy and explicitly allow unauthenticated user calls:

helm upgrade openshell \
oci://ghcr.io/nvidia/openshell/helm-chart \
--version <version> \
--namespace openshell \
--set server.disableTls=true \
--set 'gatewayConfig.openshell\.gateway\.auth.allow_unauthenticated_users=true'

The gateway listens on plaintext HTTP behind the trusted proxy, while sandbox supervisors still authenticate with gateway-minted sandbox JWTs. User-facing CLI/API calls without OIDC or mTLS credentials are accepted as an unauthenticated local developer principal. The proxy is responsible for authenticating callers and forwarding only authorized traffic.

Only enable unauthenticated users when the gateway is not reachable from outside a trusted local development environment or the proxy path is fully trusted. Never expose a plaintext, auth-disabled gateway to a public network.

Register the gateway with the CLI using the proxy’s public URL. The browser-based login flow runs automatically on first use:

openshell gateway add https://gateway.example.com --name production