Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions deploy/helm/openshell/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ Validate chart values that Helm would otherwise accept silently.
{{- if and (eq $workloadKind "statefulset") (gt $replicaCount 1) (not (get $workload "allowMultiReplicaStatefulSet" | default false)) -}}
{{- fail "replicaCount > 1 with workload.kind=statefulset requires workload.allowMultiReplicaStatefulSet=true; use workload.kind=deployment for external database-backed multi-replica gateways." -}}
{{- end -}}
{{- $adminRole := .Values.server.oidc.adminRole | default "" -}}
{{- $userRole := .Values.server.oidc.userRole | default "" -}}
{{- if and .Values.server.oidc.issuer (or (and $adminRole (not $userRole)) (and $userRole (not $adminRole))) -}}
{{- fail "server.oidc.adminRole and server.oidc.userRole must both be set or both be empty." -}}
{{- end -}}
{{- $workspaceMode := .Values.server.drivers.kubernetes.workspaceMode | default "shared" -}}
{{- if not (has $workspaceMode (list "shared" "managed" "operator")) -}}
{{- fail "server.drivers.kubernetes.workspaceMode must be one of: shared, managed, operator." -}}
Expand Down
4 changes: 0 additions & 4 deletions deploy/helm/openshell/templates/gateway-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,8 @@ data:
{{- if .Values.server.oidc.rolesClaim }}
roles_claim = {{ .Values.server.oidc.rolesClaim | quote }}
{{- end }}
{{- if .Values.server.oidc.adminRole }}
admin_role = {{ .Values.server.oidc.adminRole | quote }}
{{- end }}
{{- if .Values.server.oidc.userRole }}
user_role = {{ .Values.server.oidc.userRole | quote }}
{{- end }}
{{- if .Values.server.oidc.scopesClaim }}
scopes_claim = {{ .Values.server.oidc.scopesClaim | quote }}
{{- end }}
Expand Down
52 changes: 52 additions & 0 deletions deploy/helm/openshell/tests/oidc_role_validation_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

suite: OIDC role validation
templates:
- templates/gateway-config.yaml
- templates/statefulset.yaml

tests:
- it: rejects an admin role without a user role
template: templates/statefulset.yaml
set:
server.oidc.issuer: https://issuer.example.com
server.oidc.adminRole: openshell-admin
asserts:
- failedTemplate:
errorPattern: "server.oidc.adminRole and server.oidc.userRole must both be set or both be empty"

- it: rejects a user role without an admin role
template: templates/statefulset.yaml
set:
server.oidc.issuer: https://issuer.example.com
server.oidc.userRole: openshell-user
asserts:
- failedTemplate:
errorPattern: "server.oidc.adminRole and server.oidc.userRole must both be set or both be empty"

- it: renders both roles when RBAC mode is configured
template: templates/gateway-config.yaml
set:
server.oidc.issuer: https://issuer.example.com
server.oidc.adminRole: openshell-admin
server.oidc.userRole: openshell-user
asserts:
- matchRegex:
path: data["gateway.toml"]
pattern: '(?m)^admin_role\s*=\s*"openshell-admin"$'
- matchRegex:
path: data["gateway.toml"]
pattern: '(?m)^user_role\s*=\s*"openshell-user"$'

- it: renders empty roles for authentication-only mode
template: templates/gateway-config.yaml
set:
server.oidc.issuer: https://issuer.example.com
asserts:
- matchRegex:
path: data["gateway.toml"]
pattern: '(?m)^admin_role\s*=\s*""$'
- matchRegex:
path: data["gateway.toml"]
pattern: '(?m)^user_role\s*=\s*""$'
4 changes: 4 additions & 0 deletions docs/reference/gateway-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ namespace = "openshell"
allow_reference_namespace = false
```

Set both OIDC `admin_role` and `user_role` to empty strings to authorize every
authenticated identity. Omitting either field uses its default role name, so
set both explicitly when authentication-only mode is required.

Local Docker, Podman, and VM gateways can also set `[openshell.gateway.mtls_auth] enabled = true` to authenticate CLI callers from verified client certificates. Kubernetes deployments must leave this unset and use OIDC or a trusted access proxy; the Helm chart does not render this table.

`[openshell.gateway.tls]` supports optional SNI-based dual-certificate mode for deployments that need separate internal and external server certificates. Set `external_cert_path` and `external_key_path` to point at the external (e.g. ACME/publicly-trusted) certificate and key. List the hostnames that should be served with the external certificate in `external_server_names`. Connections whose TLS SNI hostname matches one of those names receive the external certificate; all other connections (including those with no SNI) receive the primary internal certificate from `cert_path`/`key_path`. Both fields must be set together — providing only one is a configuration error. On Kubernetes with the Helm chart, the external certificate is managed automatically when `certManager.serverIssuerRef.name` is set; the chart populates these fields from the cert-manager-issued external server certificate.
Expand Down
Loading