Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,40 @@ spec:
#
# Applied here rather than in the FluxInstance because the operator is
# installed by Helm, so the FluxInstance's kustomize patches never reach it.

# C-0211 (CIS-5.7.3) — the two non-privilege fields, supplied at TEMPLATE level.
#
# flux-system is excluded from add-pod-security-context / add-container-security-context
# because its workloads need elevated privilege by design, and the namespace-scoped
# add-baseline-context-optin-* rules cannot close the gap here: all three match
# `kinds: Pod`, so they mutate at ADMISSION and leave the stored workload spec
# Kubescape reads untouched. Only a template-level change moves the measurement —
# the same reason #3541 (velero) and #3544 (the four FluxInstance controllers) were
# done this way rather than by labelling the namespace.
#
# Measured against the live PROD stored specs 2026-09-04: of flux-system's six
# workloads, four controllers already carry both fields from #3544, leaving
# flux-operator and tofu-controller. tofu-controller is retired and pending removal
# in #3480, so flux-operator is the namespace's last workload needing this.
#
# Both fields are inert here, which is the point rather than a caveat — this changes
# a declared posture without changing how the operator runs:
# - fsGroupChangePolicy governs the kubelet's volume ownership pass, which runs only
# when a pod sets fsGroup. This pod sets none, and its only volumes are an emptyDir
# and the projected service-account token — no PVC, no hostPath.
# - seLinuxOptions {level: s0} is the default non-privileged MCS level and a no-op on
# this AppArmor cluster (runc ignores SELinux labels when SELinux is not the active
# LSM), retained as CIS-5.7.3 defense-in-depth on any SELinux node.
#
# Neither carries the runAsGroup-without-runAsUser coupling documented above, so
# neither can stop the sandbox building.
#
# 🔴 The pod-level op adds a LEAF into the chart's pod securityContext, which renders
# as `{}` (read from the live Deployment 2026-09-04). A leaf add is deliberate: adding
# the whole object would REPLACE it and silently discard any field the chart starts
# setting later, which is exactly what the +(key) anchors elsewhere exist to prevent.
# The cost is that a chart that stopped rendering the object would fail this patch —
# loudly, on a Renovate chart bump with CI in front of it, never silently.
postRenderers:
- kustomize:
patches:
Expand All @@ -61,3 +95,10 @@ spec:
- op: add
path: /spec/template/spec/containers/0/securityContext/runAsGroup
value: 65532
- op: add
path: /spec/template/spec/containers/0/securityContext/seLinuxOptions
value:
level: s0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- op: add
path: /spec/template/spec/securityContext/fsGroupChangePolicy
value: OnRootMismatch
34 changes: 33 additions & 1 deletion scripts/validate-eks-ci-role-policy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,39 @@ const (
// The previous approved aggregate digest was:
//
// 686bf5ade0d7869f3a20d50a05a7ac083744f0e88ede4fc02298ab9f67dfdf19
const expectedRenderedSurfaceSHA = "a16fbd577f8155e64aacc02cb624f26d9628d75658ce804215d9d69a3884bf92"
//
// Re-approved 2026-09-04 for the flux-operator C-0211 template fix (#3239), which
// adds two securityContext ops to that HelmRelease's existing postRenderer patch.
//
// Conservation proven by rendering ALL FIVE overlays from both trees with the same
// renderer and taking the set difference in BOTH directions over the complete
// apiVersion|kind|namespace|name identity: 548 documents on main e37660b2 and 548 on
// this branch — ZERO added, ZERO removed, ZERO renamed. Neither side carries a
// duplicate identity, so that pairing is one-to-one.
//
// The ENTIRE content delta across all five roots is seven added lines inside one
// document — the flux-operator HelmRelease — and nothing is removed anywhere:
//
// - op: add /spec/template/spec/containers/0/securityContext/seLinuxOptions {level: s0}
// - op: add /spec/template/spec/securityContext/fsGroupChangePolicy OnRootMismatch
//
// Neither op is grant-bearing: no rule, verb, resource, group, subject,
// ServiceAccount, role reference or policy moved on either side. The surface digest
// moved only because that HelmRelease is itself a selected authorization-capable
// document, so its text is covered by the aggregate — which is the tripwire working
// as designed, not a privilege change.
//
// The value below is CI's own computed digest at head 5dc2d805, taken from the
// failing run rather than recomputed locally: this validator pins the renderer to
// kubectl v1.36.2 and refuses any other, and the host that prepared this change has
// v1.36.1. The conservation proof above is renderer-robust because both sides were
// rendered with the SAME local renderer; the digest is not, so it comes from the
// pinned one.
//
// The previous approved aggregate digest was:
//
// a16fbd577f8155e64aacc02cb624f26d9628d75658ce804215d9d69a3884bf92
const expectedRenderedSurfaceSHA = "ab05bc2c95924e372c038f878872aa94e3bd81380daa96a283bd7f74e2132a69"

// authorizationOverlayPaths lists every independently reconciled production
// layer where an object can grant privileges to the aws/aws service account.
Expand Down
Loading