Repository navigation
Make the Restricted workload profile usable and limit agent credentials to the agent #714
Description
Setting podSecurity.enforceRestricted=true labels the games namespace but does not make generated game pods satisfy Restricted admission. On a cluster enforcing PSA without exemptions or a mutating admission layer, normal game pods are rejected, including templates specifying a nonroot UID. Operators currently cannot obtain the advertised namespace hardening simply by enabling the option.
This is static inspection of 04e41075cafc4c1a99bcb3723b0a8745ee810957, not a runtime reproduction. It follows #503, which corrected documentation to describe existing game-container defaults. The issue requests a working opt-in profile plus related in-pod credential hardening; it does not claim a PSA bypass or proven node escape.
Evidence:
- The chart option defaults off and only adds namespace admission labels.
- Game security context is nil or only UID/GID, pod context only supplies FSGroup, and config-init has no security context.
- Capture requires privilege escalation and NET_RAW, incompatible with Restricted.
- The pod chooses the agent ServiceAccount and shares its process namespace; token automount is not disabled. The default agent grant is limited to get/patch of its own GameServer status. It is not cluster-admin authority.
Recommended implementation:
- Wire an explicit workload-security profile into reconciliation and validate module compatibility before admission failure. Apply appropriate nonroot identities, volume ownership, seccomp, capability drops, and escalation restrictions to game and init containers. For compatible images:
# Fragment of PodSpec; select compatible per-container UIDs.
securityContext:
runAsNonRoot: true
seccompProfile: {type: RuntimeDefault}
containers:
- name: game
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
initContainers:
- name: config-init
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}- Reject incompatible capture requests with a clear condition, or explicitly design a separately authorized exception profile. Do not weaken the whole namespace implicitly. Select a supported PSA version policy instead of unexplained
latestdrift. - Disable pod-level service-account token automount. Project a short-lived token, CA certificate, and namespace only into the agent at its existing client configuration paths, preserving rotation and the narrow per-server Role. Game/config-init containers need no API credentials.
- Make shared PID namespace a deliberate profile decision. Agent-only volume mounts are insufficient as a strict credential boundary when
/proc/<pid>/rootis accessible under Unix/process permissions. Preserve metrics through a compatible alternative or document the profile's remaining in-pod trust assumption. Agent leaf certificates are ServerAuth-only, so their theft does not automatically authenticate a client to other agents.
Acceptance criteria:
- CI admits representative game/config-init pods under enforced Restricted PSA and verifies startup, writable data, and upgrades.
- Incompatible modules/capture produce actionable errors before repeated failed pod creation; compatible existing installs have a documented migration path.
- Game and init containers lack mounted API tokens; agent heartbeats survive projected-token rotation.
- Security checks cover every regular, init, and optional ephemeral container and verify the chosen process-sharing behavior.
- Documentation distinguishes Restricted compliance, namespace isolation, and the residual trust shared by containers within one pod.
Activity
ValgulNecron commentedon Oct 20, 2026
Thanks, confirmed on master:
podSecurity.enforceRestrictedonly labels the games namespace (charts/gameplane/templates/namespaces.yaml:8-10), while the game and config-init containers set none of the fields Restricted requires (operator/internal/controller/gameserver_controller.go:2136-2144,buildConfigInitContainer), so turning it on makes game pods fail admission. The game container also gets the agent ServiceAccount token mounted.Go ahead with a PR. Decisions on the open points:
runAsNonRoot,allowPrivilegeEscalation: false,capabilities.drop: [ALL]andseccompProfile: RuntimeDefaulton the game and config-init containers when the profile is on, and stop exposing the agent's ServiceAccount token to the game container (only the agent should have it)./procfor CPU and memory), and document the in-pod trust assumption indocs/security.md.enforce-version: latestwith a pinned, tested version that admins can override in values, so a Kubernetes upgrade can't silently start rejecting game pods.Please also correct
docs/security.md:370-372in the same PR: it currently tells hostile-module operators to enableenforceRestricted, which breaks game pods until this lands.Baylem commentedon Oct 25, 2026
Implemented in #764: compatible Restricted workloads, agent-only token projection, pinned overridable PSA version, and an audited administrator node-capture exception. Shared PID remains for metrics and the remaining in-pod trust assumptions are documented. The latest follow-up revalidates diagnostic namespace authorization throughout the capture lifecycle.