Skip to content

Tenant Operator-generated StatefulSet cannot satisfy PodSecurity "restricted" — CRD does not expose container-level securityContext #167

Description

@kutekahuna

The rustfs-operator generates a StatefulSet whose container-level securityContext is empty. On clusters that enforce Kubernetes Pod Security Admission at the restricted level (a common default in production and required by many CIS/hardening baselines), pod creation is blocked, and the tenant is stuck reconciling with 0 replicas indefinitely.

The Tenant CRD (tenants.rustfs.com/v1alpha1) does expose a spec.securityContext, but only four fields (fsGroup, runAsGroup, runAsUser, runAsNonRoot) .

Reproduction

  1. Create a namespace with PSA enforce restricted:
    apiVersion: v1
    kind: Namespace
    metadata:
    name: rustfs-tenant
    labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
  2. Apply a minimal Tenant CR in that namespace with image: rustfs/rustfs:1.0.0-beta.8.
  3. Observe: StatefulSet is created; pod creation is denied.

Observed error

Warning FailedCreate ... statefulset-controller
Create Pod -pool-0-0 in StatefulSet -pool-0 failed:
pods "-pool-0-0" is forbidden: violates PodSecurity "restricted:latest":
allowPrivilegeEscalation != false
(container "rustfs" must set securityContext.allowPrivilegeEscalation=false)
unrestricted capabilities
(container "rustfs" must set securityContext.capabilities.drop=["ALL"])
runAsNonRoot != true
(pod or container "rustfs" must set securityContext.runAsNonRoot=true)
seccompProfile
(pod or container "rustfs" must set securityContext.seccompProfile.type
to "RuntimeDefault" or "Localhost")

The reconciler re-emits StatefulSetUpdateStarted continuously. Tenant remains in Reconciling with Replicas: 0.

Current CRD support

spec.securityContext on tenants.rustfs.com only accepts:

  • fsGroup
  • runAsGroup
  • runAsUser
  • runAsNonRoot

Missing (and required by restricted):

  • allowPrivilegeEscalation
  • capabilities (specifically drop: [ALL])
  • seccompProfile
  • readOnlyRootFilesystem (nice-to-have)

spec.pools[*] also does not expose a per-pool/container securityContext.

Also , external patches don't help (ex kustomize patch)

Because the StatefulSet is generated by the operator at reconcile time, downstream tooling (Kustomize/Flux/Helm post-render) cannot patch it — the resource does not exist at deploy time. Users are forced to either (a) relax PSA on the namespace to baseline / privileged (weakens cluster-wide security posture), or (b) run a mutating admission webhook to inject the missing fields (fragile and out-of-band).

Requested change

  1. Expose full container securityContext on the Tenant CRD, ideally at both spec.securityContext (defaults for all pools) and spec.pools[].securityContext (per-pool override). Fields to accept:
    - allowPrivilegeEscalation
    - capabilities.add / capabilities.drop
    - seccompProfile
    - readOnlyRootFilesystem
    - existing runAsUser/runAsGroup/runAsNonRoot
  2. Set safe defaults in the operator that satisfy PSA restricted out of the box:
    allowPrivilegeEscalation: false
    capabilities:
    drop: [ALL]
    runAsNonRoot: true
    seccompProfile:
    type: RuntimeDefault

Environment

  • rustfs image: rustfs/rustfs:1.0.0-beta.8
  • rustfs-operator: (latest)
  • Kubernetes: RKE2 (v1.33)
  • PSA enforce level on tenant namespace: restricted:latest

Workaround in place

Relaxed PSA on the tenant namespace to baseline. Not acceptable long-term for a production/hardened cluster.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions