fix: PSS restricted compliance, missing IAM permissions, Gateway API support#4
Merged
Merged
Conversation
…support
Three fixes discovered while deploying pgdog-control on EKS with
Pod Security Standards enforcement:
1. **PSS Restricted compliance**: Add `runAsNonRoot: true`,
`runAsUser: 65534`, `runAsGroup: 65534` (nobody) to the control
deployment's pod securityContext. The container already sets
`allowPrivilegeEscalation: false`, drops ALL capabilities, and
uses RuntimeDefault seccomp — but omitting `runAsNonRoot` causes
PSS Restricted admission to reject the pod. The control binary
has no dependency on running as root.
2. **Missing IAM permissions in docs**: The IRSA permissions policy
in the README was missing `rds:DescribeDBParameters` and
`ec2:DescribeInstanceTypes`. Without these, the RDS refresh loop
fails with AccessDenied/UnauthorizedOperation and the database
panel stays empty, even though DescribeDBInstances and
DescribeDBClusters succeed.
3. **Gateway API (HTTPRoute) support**: Add `ingress.mode: gateway`
which renders an HTTPRoute instead of an Ingress. This is needed
on clusters that route traffic through a Gateway controller
(Traefik, Envoy Gateway, AWS ALB via gateway.k8s.aws) rather
than through an IngressClass. The HTTPRoute attaches to an
existing Gateway via `ingress.gateway.{name,namespace,sectionName}`.
Running as uid 65534 (nobody) sets HOME=/nonexistent, which doesn't exist and isn't writable. Helm's `repo add` writes config to $HOME and fails with `mkdir /nonexistent: permission denied`. Setting HOME=/tmp gives helm a writable directory.
The image ships with ubuntu:1000 and its home dir /home/ubuntu exists. Using this instead of nobody (65534) avoids the HOME=/tmp workaround needed for helm repo config writes.
levkk
approved these changes
May 25, 2026
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three fixes discovered while deploying pgdog-control on EKS (K8s 1.35) with Pod Security Standards enforcement:
1. PSS Restricted compliance
The control deployment's pod
securityContextonly setseccompProfile: RuntimeDefault. Namespaces withpod-security.kubernetes.io/enforce=restrictedreject pods that don't setrunAsNonRoot: true. The container-level context already drops ALL capabilities and disables privilege escalation, but the missing pod-level field blocks admission.Fix: Add
runAsNonRoot: true,runAsUser: 65534,runAsGroup: 65534(nobody) to the pod securityContext. The control binary binds port 8080 (unprivileged), reads config from a ConfigMap mount (world-readable), and has no filesystem write requirements — verified working as non-root on EKS.2. Missing IAM permissions in README
The documented IRSA permissions policy was missing two actions the control plane actually calls:
rds:DescribeDBParameters— called afterDescribeDBInstancesto display parameter group settings. Without it, the RDS refresh loop fails withAccessDeniedand the database panel stays empty.ec2:DescribeInstanceTypes— called to resolve instance class specs (vCPU, memory) for each RDS instance. Without it, the refresh fails withUnauthorizedOperation.Both are read-only. The
DescribeDBInstancesandDescribeDBClusterscalls succeed, but the refresh is all-or-nothing — one denied action causes the entire refresh to report failure.Found via CloudTrail after the dashboard showed no RDS instances despite successful STS token exchange and correct IRSA wiring.
3. Gateway API (HTTPRoute) support
Added
ingress.mode: gatewaywhich renders an HTTPRoute instead of an Ingress. On clusters that use Gateway API (Traefik, Envoy Gateway, AWS ALB controller viagateway.k8s.aws), there's no IngressClass to target. The existing modes (nginx,aws,default) all render Ingress resources.The HTTPRoute attaches to an existing Gateway via three new values:
ingress.gateway.name— Gateway resource nameingress.gateway.namespace— Gateway namespaceingress.gateway.sectionName— optional listener selectorExample:
Test plan
enforce=restrictednamespace — pods admitted without warningsidinside container returnsuid=65534(nobody)instances=1in logs)https://pgdog-dash.staging.platform.reducto.ai/🤖 Generated with Claude Code