From 01f4d63239388bea51b6943280993445ab465249 Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Sun, 27 Sep 2026 09:49:18 +0100 Subject: [PATCH] fix(helm): pass Restricted Pod Security on certgen hook Add runAsNonRoot and seccompProfile so the certgen Job passes Restricted PSA. Values are configurable via pkiInitJob.podSecurityContext and pkiInitJob.securityContext, shared by both certgen Jobs instead of duplicated inline blocks. Fixes #3215 Signed-off-by: Eric Curtin --- deploy/helm/openshell/README.md | 2 + deploy/helm/openshell/templates/certgen.yaml | 18 +++--- .../tests/certgen_security_context_test.yaml | 55 +++++++++++++++++++ deploy/helm/openshell/values.yaml | 13 +++++ 4 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 deploy/helm/openshell/tests/certgen_security_context_test.yaml diff --git a/deploy/helm/openshell/README.md b/deploy/helm/openshell/README.md index 4d09c32de8..052a140ab6 100644 --- a/deploy/helm/openshell/README.md +++ b/deploy/helm/openshell/README.md @@ -242,6 +242,8 @@ discovery endpoint or its TLS CA. | openshiftRoute.host | string | `""` | Hostname for the Route. Must match a SAN on the gateway's server cert. | | pkiInitJob.enabled | bool | `true` | Run a pre-install/pre-upgrade Job that creates gateway and client mTLS Secrets. When certManager.enabled=true, cert-manager owns TLS and this same hook runs in JWT-only mode even if pkiInitJob.enabled remains true. | | pkiInitJob.failOnTimeout | bool | `true` | Fail the helm install/upgrade if cert-manager does not issue the certificate within the polling timeout. When true (default), the install fails immediately if the timeout is reached, providing clear feedback that BackendTLSPolicy is non-functional. When false, the hook succeeds with a warning and you can run `helm upgrade` after cert-manager issues the certificate to create the backend CA ConfigMap. If you set this to false and see "TLS error: Secret is not supplied by SDS" when connecting to the gateway, check if the TLS secret exists and run `helm upgrade` to create the ConfigMap. | +| pkiInitJob.podSecurityContext | object | `{"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Pod securityContext for the certgen hook Jobs. Defaults satisfy the Restricted Pod Security Standard. | +| pkiInitJob.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsUser":1000}` | Container securityContext for the certgen hook Jobs. | | pkiInitJob.serverDnsNames | list | `[]` | Extra DNS SANs to append to the server certificate. | | pkiInitJob.serverIpAddresses | list | `[]` | Extra IP SANs to append to the server certificate. | | pkiInitJob.timeoutSeconds | int | `120` | Maximum time in seconds for the certgen hook to poll for cert-manager certificates. When using cert-manager with BackendTLSPolicy, the hook polls for this many seconds waiting for the certificate to be issued, then creates the backend CA ConfigMap. The Job deadline is set to (timeoutSeconds + 30) to allow time for ConfigMap creation and cleanup. Increase this if cert-manager takes longer than 120 seconds to issue certificates. | diff --git a/deploy/helm/openshell/templates/certgen.yaml b/deploy/helm/openshell/templates/certgen.yaml index f7c9a751d3..8d2e81faa6 100644 --- a/deploy/helm/openshell/templates/certgen.yaml +++ b/deploy/helm/openshell/templates/certgen.yaml @@ -79,6 +79,10 @@ spec: spec: restartPolicy: OnFailure serviceAccountName: {{ $hookName }} + {{- with .Values.pkiInitJob.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -88,10 +92,7 @@ spec: image: {{ include "openshell.image" . | quote }} imagePullPolicy: {{ .Values.gateway.image.pullPolicy | default .Values.global.image.pullPolicy }} securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL + {{- toYaml .Values.pkiInitJob.securityContext | nindent 12 }} env: - name: POD_NAMESPACE valueFrom: @@ -150,6 +151,10 @@ spec: spec: restartPolicy: OnFailure serviceAccountName: {{ $hookName }} + {{- with .Values.pkiInitJob.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -159,10 +164,7 @@ spec: image: {{ include "openshell.image" . | quote }} imagePullPolicy: {{ .Values.gateway.image.pullPolicy | default .Values.global.image.pullPolicy }} securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL + {{- toYaml .Values.pkiInitJob.securityContext | nindent 12 }} env: - name: POD_NAMESPACE valueFrom: diff --git a/deploy/helm/openshell/tests/certgen_security_context_test.yaml b/deploy/helm/openshell/tests/certgen_security_context_test.yaml new file mode 100644 index 0000000000..d82d0a024e --- /dev/null +++ b/deploy/helm/openshell/tests/certgen_security_context_test.yaml @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +suite: certgen hook securityContext +templates: + - templates/certgen.yaml +release: + name: openshell + namespace: my-namespace + +tests: + - it: renders a Restricted-compliant pod and container securityContext by default + template: templates/certgen.yaml + documentIndex: 3 + asserts: + - equal: + path: spec.template.spec.securityContext.runAsNonRoot + value: true + - equal: + path: spec.template.spec.securityContext.seccompProfile.type + value: RuntimeDefault + - equal: + path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.capabilities.drop[0] + value: ALL + + - it: renders an explicitly set pkiInitJob.podSecurityContext + template: templates/certgen.yaml + documentIndex: 3 + set: + pkiInitJob.podSecurityContext: + runAsNonRoot: true + runAsUser: 2000 + seccompProfile: + type: RuntimeDefault + asserts: + - equal: + path: spec.template.spec.securityContext.runAsUser + value: 2000 + + - it: renders the same securityContext on the cert-manager backend-ca hook + template: templates/certgen.yaml + set: + certManager.enabled: true + grpcRoute.backendTLSPolicy.enabled: true + documentIndex: 4 + asserts: + - equal: + path: spec.template.spec.securityContext.runAsNonRoot + value: true + - equal: + path: spec.template.spec.containers[0].securityContext.capabilities.drop[0] + value: ALL diff --git a/deploy/helm/openshell/values.yaml b/deploy/helm/openshell/values.yaml index 426f3ae424..548a37cd38 100644 --- a/deploy/helm/openshell/values.yaml +++ b/deploy/helm/openshell/values.yaml @@ -532,6 +532,19 @@ pkiInitJob: # see "TLS error: Secret is not supplied by SDS" when connecting to the gateway, # check if the TLS secret exists and run `helm upgrade` to create the ConfigMap. failOnTimeout: true + # -- Pod securityContext for the certgen hook Jobs. Defaults satisfy the + # Restricted Pod Security Standard. + podSecurityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + # -- Container securityContext for the certgen hook Jobs. + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL # cert-manager Certificate/Issuer resources (requires cert-manager CRDs in-cluster). # Does not install cert-manager itself.