88 lines
2.9 KiB
YAML
88 lines
2.9 KiB
YAML
apiVersion: templates.gatekeeper.sh/v1beta1
|
|
kind: ConstraintTemplate
|
|
metadata:
|
|
name: k8spodsecurity
|
|
annotations:
|
|
description: "Enforces pod security standards including privileged containers, host namespaces, and capabilities"
|
|
spec:
|
|
crd:
|
|
spec:
|
|
names:
|
|
kind: K8sPodSecurity
|
|
validation:
|
|
openAPIV3Schema:
|
|
type: object
|
|
properties:
|
|
allowPrivileged:
|
|
type: boolean
|
|
description: "Allow privileged containers"
|
|
allowHostNamespace:
|
|
type: boolean
|
|
description: "Allow host namespace usage"
|
|
allowedCapabilities:
|
|
type: array
|
|
description: "List of allowed capabilities"
|
|
items:
|
|
type: string
|
|
targets:
|
|
- target: admission.k8s.gatekeeper.sh
|
|
rego: |
|
|
package k8spodsecurity
|
|
|
|
import future.keywords.contains
|
|
import future.keywords.if
|
|
|
|
violation[{"msg": msg}] {
|
|
not input.parameters.allowPrivileged
|
|
container := input.review.object.spec.containers[_]
|
|
container.securityContext.privileged == true
|
|
msg := sprintf("Privileged container not allowed: %v", [container.name])
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
container := input.review.object.spec.containers[_]
|
|
not container.securityContext.runAsNonRoot
|
|
msg := sprintf("Container must run as non-root: %v", [container.name])
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
container := input.review.object.spec.containers[_]
|
|
not container.securityContext.readOnlyRootFilesystem
|
|
msg := sprintf("Container must use read-only root filesystem: %v", [container.name])
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
not input.parameters.allowHostNamespace
|
|
input.review.object.spec.hostPID == true
|
|
msg := "Host PID namespace not allowed"
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
not input.parameters.allowHostNamespace
|
|
input.review.object.spec.hostIPC == true
|
|
msg := "Host IPC namespace not allowed"
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
not input.parameters.allowHostNamespace
|
|
input.review.object.spec.hostNetwork == true
|
|
msg := "Host network namespace not allowed"
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
volume := input.review.object.spec.volumes[_]
|
|
volume.hostPath
|
|
msg := sprintf("hostPath volume not allowed: %v", [volume.name])
|
|
}
|
|
|
|
violation[{"msg": msg}] {
|
|
container := input.review.object.spec.containers[_]
|
|
capability := container.securityContext.capabilities.add[_]
|
|
not is_allowed_capability(capability)
|
|
msg := sprintf("Capability %v not allowed for container: %v", [capability, container.name])
|
|
}
|
|
|
|
is_allowed_capability(capability) {
|
|
input.parameters.allowedCapabilities[_] == capability
|
|
}
|