security: implement proper security hardening

Instead of just skipping security checks, properly fix the issues:

**Pod & Container Security Context:**
- Add runAsUser: 1000 (non-root)
- Add runAsGroup: 1000
- Add fsGroup: 1000 for volume permissions
- Add seccompProfile: RuntimeDefault
- Drop ALL capabilities (principle of least privilege)

**Resource Management:**
- Add ephemeral-storage requests (1Gi) and limits (2Gi)

**Health Checks:**
- Change thelounge liveness probe from TCP to HTTP
- Reduces false positives and provides better health signals

**Reduced Exceptions:**
- Removed 6+ security check exceptions
- Now only skip: image tags (intentional), read-only FS (apps need writes)
- Removed Polaris runAsRootAllowed exemptions

**Note:** If containers fail to start post-merge, may need to adjust UIDs
or add specific capabilities. LinuxServer images may need tweaking.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
2026-02-08 10:06:36 -05:00
parent 43d6bab89e
commit 9c70b82fb3
4 changed files with 39 additions and 18 deletions
+3 -9
View File
@@ -5,12 +5,6 @@ framework:
- all
skip-check:
- CKV_K8S_21 # Default namespace usage
- CKV_K8S_43 # Image tag validation
- CKV_K8S_40 # High UID requirement
- CKV_K8S_29 # Security context
- CKV_K8S_23 # Root containers
- CKV_K8S_37 # Container capabilities
- CKV_K8S_22 # Read-only filesystem
- CKV_K8S_28 # NET_RAW capability
- CKV_K8S_31 # Seccomp profile
- CKV_K8S_14 # Image tag should be fixed
- CKV_K8S_43 # Image tag validation (using latest tags intentionally)
- CKV_K8S_14 # Image tag should be fixed (same as above)
- CKV_K8S_22 # Read-only filesystem (IRC apps need to write to volumes)
-4
View File
@@ -37,12 +37,8 @@ jobs:
kubectl kustomize . | kube-score score - \
--ignore-test pod-networkpolicy \
--ignore-test deployment-has-poddisruptionbudget \
--ignore-test container-security-context-user-group-id \
--ignore-test container-security-context-readonlyrootfilesystem \
--ignore-test statefulset-has-servicename \
--ignore-test container-image-tag \
--ignore-test container-ephemeral-storage-request-and-limit \
--ignore-test probe-not-identical \
--output-format ci
fi
+19 -2
View File
@@ -6,7 +6,6 @@ metadata:
app.kubernetes.io/name: thelounge
app.kubernetes.io/instance: thelounge
annotations:
polaris.fairwinds.com/runAsRootAllowed-exempt: "true"
polaris.fairwinds.com/tagNotSpecified-exempt: "true"
polaris.fairwinds.com/topologySpreadConstraint-exempt: "true"
spec:
@@ -24,11 +23,26 @@ spec:
spec:
priorityClassName: low-priority
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: thelounge
image: ghcr.io/thelounge/thelounge:latest
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
ports:
- containerPort: 9000
name: http-9000
@@ -39,11 +53,14 @@ spec:
requests:
cpu: "100m"
memory: "256Mi"
ephemeral-storage: "1Gi"
limits:
cpu: "500m"
memory: "512Mi"
ephemeral-storage: "2Gi"
livenessProbe:
tcpSocket:
httpGet:
path: /
port: 9000
initialDelaySeconds: 20
periodSeconds: 10
+17 -3
View File
@@ -6,7 +6,6 @@ metadata:
app.kubernetes.io/name: znc
app.kubernetes.io/instance: znc
annotations:
polaris.fairwinds.com/runAsRootAllowed-exempt: "true"
polaris.fairwinds.com/tagNotSpecified-exempt: "true"
polaris.fairwinds.com/topologySpreadConstraint-exempt: "true"
spec:
@@ -24,6 +23,13 @@ spec:
spec:
priorityClassName: low-priority
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: znc
image: lscr.io/linuxserver/znc:latest
@@ -33,9 +39,15 @@ spec:
name: irc-6501
securityContext:
runAsNonRoot: false
allowPrivilegeEscalation: false
privileged: false
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: config
@@ -45,9 +57,11 @@ spec:
requests:
memory: "256Mi"
cpu: "100m"
ephemeral-storage: "1Gi"
limits:
memory: "512Mi"
cpu: "500m"
ephemeral-storage: "2Gi"
livenessProbe:
tcpSocket: