Skip to content

bug(helm): certgen hook is rejected by Restricted Pod Security #3215

Description

@jtatum

User Story

As a Kubernetes platform operator enforcing the Restricted Pod Security Standard on controller namespaces, I want the OpenShell Helm chart's certificate-generation hook to pass admission, so that I can install the gateway without weakening the namespace security policy.

Problem Statement

OpenShell Helm chart 0.0.116 renders Job/<release>-certgen without a pod securityContext and without runAsNonRoot or seccompProfile on its container. The container already drops all capabilities and disables privilege escalation, but Kubernetes Restricted Pod Security admission still rejects the hook for the missing non-root and seccomp settings.

The main gateway workload can already be configured with podSecurityContext and securityContext; the certgen hook does not inherit those settings and exposes no equivalent values.

Impact / Why This Matters

The pre-install/pre-upgrade hook blocks the entire Helm release in a namespace labeled pod-security.kubernetes.io/enforce: restricted. Operators must either weaken admission for the trusted gateway namespace or carry a Flux/Helm post-render patch for a security-sensitive hook. The post-render workaround is coupled to the hook resource name and container position and can silently stop matching after a chart refactor unless it is separately tested.

Acceptance Criteria

  • A default helm template render of the certgen Job satisfies the Restricted Pod Security Standard for the chart's supported Kubernetes versions.
  • The certgen pod and container run as non-root and declare a Restricted-compatible seccomp profile.
  • The chart exposes certgen-specific pod/container security-context values if operators need to override the defaults.
  • Chart tests cover the rendered certgen security context.
  • Existing installs that do not enforce Pod Security continue to upgrade without manual migration.

Reproduction Steps

  1. Create a namespace with pod-security.kubernetes.io/enforce: restricted (tested with policy version v1.36).
  2. Install OpenShell chart 0.0.116 with Agent Sandbox available and pkiInitJob.enabled: true.
  3. Observe that Job/<release>-certgen is rejected by Pod Security admission for missing runAsNonRoot and seccompProfile fields.
  4. Render the chart and compare the certgen Job with the configurable gateway StatefulSet security contexts.

Environment

  • OpenShell Helm chart: 0.0.116, OCI digest sha256:df55cd1538bdfb7836834c30dfcf8373b85ffea83bbfd70d50dbe69407a0d2b3
  • Kubernetes: v1.36.4
  • Distribution: Talos Linux v1.13.9
  • Deployment: Flux HelmRelease, Kubernetes Agent Sandbox driver

Logs

The rendered certgen container has allowPrivilegeEscalation: false and drops ALL, but neither the pod nor container declares runAsNonRoot or seccompProfile. Restricted admission reports those missing fields under the restricted policy.

Activity

  1. added
    state:acceptedA maintainer decided OpenShell should pursue this issue
    and removed
    state:triage-neededOpened without agent diagnostics and needs triage
    on Sep 8, 2026
  2. lunarwhite commented on Sep 14, 2026

    @lunarwhite
    Contributor

    🏗️ build-plan

    Implementation Plan

    Issue type: fix
    Complexity: Low
    Confidence: High — clear path

    Summary

    The certgen hook's container securityContext omits runAsNonRoot and
    seccompProfile.type, and the gateway's securityContext omits seccompProfile. The
    hook fails first at helm.sh/hook-weight: "-20", masking the second rejection, so
    fixing only the hook leaves a default install still rejected by Restricted admission.
    Both fields are added at container level, where Restricted accepts all four controls.

    Scope

    • deploy/helm/openshell/templates/certgen.yaml: add runAsNonRoot: true and
      seccompProfile.type: RuntimeDefault to the hook's existing container
      securityContext (lines 85-89).
    • deploy/helm/openshell/values.yaml: add seccompProfile.type: RuntimeDefault to the
      gateway securityContext (lines 124-134).
    • deploy/helm/openshell/tests/certgen_test.yaml: assert the two new hook fields.
    • deploy/helm/openshell/tests/gateway_pod_security_context_test.yaml: assert the
      gateway container profile. The file has no container-level assertions today.
    • deploy/helm/openshell/README.md: regenerated by mise run helm:docs;
      mise run helm:docs:check is a required CI gate.

    Implementation Steps

    1. Add the two fields to the hook's container securityContext. No new values and no
      pod-level block: the hook renders exactly one container, and Restricted accepts
      runAsNonRoot and seccompProfile.type at container level.
    2. Add seccompProfile.type: RuntimeDefault to the gateway securityContext. It reaches
      ci/values-openshift-scc.yaml automatically, because Helm deep-merges values files.
    3. Add the two test assertions. Verify with mise run helm:test.
    4. Regenerate the chart README and confirm mise run helm:docs:check passes.
    5. Verify on a k3d cluster with pod-security.kubernetes.io/enforce=restricted that the
      hook Job completes and the gateway pod reaches Ready.

    Test Plan

    • Unit tests: certgen_test.yaml asserts runAsNonRoot and seccompProfile.type on
      the default render. gateway_pod_security_context_test.yaml gains one case asserting
      the gateway container seccompProfile.type.
    • Integration tests: N/A. Chart rendering has no integration layer between the unit
      render and a live cluster.
    • E2E tests: No e2e/ change. e2e/with-kube-gateway.sh already runs the certgen
      hook on every Kubernetes E2E run.
    • Manual verification: required. helm template proves the fields render, not that a
      Restricted-enforcing namespace admits both workloads.

    Risks & Open Questions

    • No override values are added. No known configuration needs them, and the defaults are
      OpenShift restricted-v2 compatible (runAsNonRoot with no runAsUser). Confirm this
      satisfies the "exposes certgen-specific pod/container security-context values if
      operators need to override the defaults" criterion.
    • RuntimeDefault newly applies the container runtime's syscall filter to the gateway,
      the only part of this change that alters a long-running workload on upgrade. This is
      why manual cluster verification is warranted rather than optional.
    • Gateway seccomp is set at container level because ci/values-openshift-scc.yaml nulls
      podSecurityContext, which would discard a pod-level profile on OpenShift.
    • No LSM impact: seccomp is syscall filtering, orthogonal to SELinux and AppArmor
      label-based access control.

    Documentation Impact

    • deploy/helm/openshell/README.md — regenerated (CI-enforced). No prose or reference
      page changes: the fix removes a failure mode rather than adding an operator knob.

    Revision 1 — initial plan

  3. lunarwhite commented on Sep 14, 2026

    @lunarwhite
    Contributor

    will raise a PR based on above plan later if no other comments

  4. lunarwhite commented on Sep 17, 2026

    @lunarwhite
    Contributor

    PR is ready for review: #3340

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:acceptedA maintainer decided OpenShell should pursue this issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions