diff --git a/library/general/allowedrepos/samples/repo-must-be-openpolicyagent/disallowed_both.yaml b/library/general/allowedrepos/samples/repo-must-be-openpolicyagent/disallowed_both.yaml index b19d8ea39..bec477884 100644 --- a/library/general/allowedrepos/samples/repo-must-be-openpolicyagent/disallowed_both.yaml +++ b/library/general/allowedrepos/samples/repo-must-be-openpolicyagent/disallowed_both.yaml @@ -17,3 +17,10 @@ spec: limits: cpu: "100m" memory: "30Mi" + ephemeralContainers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/library/general/allowedrepos/suite.yaml b/library/general/allowedrepos/suite.yaml index 3367d88e8..2abc4a6c4 100644 --- a/library/general/allowedrepos/suite.yaml +++ b/library/general/allowedrepos/suite.yaml @@ -26,8 +26,10 @@ tests: - name: both-disallowed object: samples/repo-must-be-openpolicyagent/disallowed_both.yaml assertions: - - violations: 2 + - violations: 3 - message: initContainer violations: 1 - message: container violations: 1 + - message: ephemeralContainer + violations: 1 diff --git a/library/general/allowedrepos/template.yaml b/library/general/allowedrepos/template.yaml index 9eb745af7..934d1a0e0 100644 --- a/library/general/allowedrepos/template.yaml +++ b/library/general/allowedrepos/template.yaml @@ -38,3 +38,10 @@ spec: not any(satisfied) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] + not any(satisfied) + msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) + } diff --git a/library/general/automount-serviceaccount-token/template.yaml b/library/general/automount-serviceaccount-token/template.yaml index 15d4650f7..ff8ab9de5 100644 --- a/library/general/automount-serviceaccount-token/template.yaml +++ b/library/general/automount-serviceaccount-token/template.yaml @@ -45,6 +45,8 @@ spec: c := input.review.object.spec.initContainers[_] } + # Ephemeral containers not checked as it is not possible to set field. + has_key(x, k) { _ = x[k] } diff --git a/library/general/containerlimits/template.yaml b/library/general/containerlimits/template.yaml index 367158ac6..8207aec89 100644 --- a/library/general/containerlimits/template.yaml +++ b/library/general/containerlimits/template.yaml @@ -172,6 +172,8 @@ spec: general_violation[{"msg": msg, "field": "initContainers"}] } + # Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/library/general/containerrequests/template.yaml b/library/general/containerrequests/template.yaml index d17a84146..d51d3f7c2 100644 --- a/library/general/containerrequests/template.yaml +++ b/library/general/containerrequests/template.yaml @@ -172,6 +172,8 @@ spec: general_violation[{"msg": msg, "field": "initContainers"}] } + # Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/library/general/containerresourceratios/template.yaml b/library/general/containerresourceratios/template.yaml index 1325591e0..010c4dc62 100644 --- a/library/general/containerresourceratios/template.yaml +++ b/library/general/containerresourceratios/template.yaml @@ -182,6 +182,8 @@ spec: general_violation[{"msg": msg, "field": "initContainers"}] } + # Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/library/general/disallowedtags/samples/container-image-must-not-have-latest-tag/example_disallowed_tag_ephemeral.yaml b/library/general/disallowedtags/samples/container-image-must-not-have-latest-tag/example_disallowed_tag_ephemeral.yaml new file mode 100644 index 000000000..66db83c15 --- /dev/null +++ b/library/general/disallowedtags/samples/container-image-must-not-have-latest-tag/example_disallowed_tag_ephemeral.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed-ephemeral +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/library/general/disallowedtags/suite.yaml b/library/general/disallowedtags/suite.yaml index 71e4941b8..5de29d5cc 100644 --- a/library/general/disallowedtags/suite.yaml +++ b/library/general/disallowedtags/suite.yaml @@ -23,6 +23,10 @@ tests: object: samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml assertions: - violations: yes + - name: single-disallowed-tag-ephemeral + object: samples/container-image-must-not-have-latest-tag/example_disallowed_tag_ephemeral.yaml + assertions: + - violations: yes - name: some-disallow-tags object: samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml assertions: diff --git a/library/general/disallowedtags/template.yaml b/library/general/disallowedtags/template.yaml index 02020d06c..bf424dee2 100644 --- a/library/general/disallowedtags/template.yaml +++ b/library/general/disallowedtags/template.yaml @@ -61,6 +61,9 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } libs: - | package lib.exempt_container diff --git a/library/general/imagedigests/samples/container-image-must-have-digest/example_disallowed.yaml b/library/general/imagedigests/samples/container-image-must-have-digest/example_disallowed.yaml index 5ef88edae..62e91f4a8 100644 --- a/library/general/imagedigests/samples/container-image-must-have-digest/example_disallowed.yaml +++ b/library/general/imagedigests/samples/container-image-must-have-digest/example_disallowed.yaml @@ -3,6 +3,13 @@ kind: Pod metadata: name: opa-disallowed spec: + initContainers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" containers: - name: opa image: openpolicyagent/opa:0.9.2 @@ -10,3 +17,10 @@ spec: - "run" - "--server" - "--addr=localhost:8080" + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/library/general/imagedigests/suite.yaml b/library/general/imagedigests/suite.yaml index 319f477f4..027f256bd 100644 --- a/library/general/imagedigests/suite.yaml +++ b/library/general/imagedigests/suite.yaml @@ -14,4 +14,10 @@ tests: - name: example-disallowed object: samples/container-image-must-have-digest/example_disallowed.yaml assertions: - - violations: yes + - violations: 3 + - message: initContainer + violations: 1 + - message: container + violations: 1 + - message: ephemeralContainer + violations: 1 diff --git a/library/general/imagedigests/template.yaml b/library/general/imagedigests/template.yaml index e50e2fc69..9a6614578 100644 --- a/library/general/imagedigests/template.yaml +++ b/library/general/imagedigests/template.yaml @@ -52,6 +52,14 @@ spec: not all(satisfied) msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] + not all(satisfied) + msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) + } libs: - | package lib.exempt_container diff --git a/library/pod-security-policy/allow-privilege-escalation/samples/psp-allow-privilege-escalation-container/example_disallowed_ephemeral.yaml b/library/pod-security-policy/allow-privilege-escalation/samples/psp-allow-privilege-escalation-container/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..5992f96b3 --- /dev/null +++ b/library/pod-security-policy/allow-privilege-escalation/samples/psp-allow-privilege-escalation-container/example_disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-privilege-escalation-disallowed + labels: + app: nginx-privilege-escalation +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + allowPrivilegeEscalation: true diff --git a/library/pod-security-policy/allow-privilege-escalation/suite.yaml b/library/pod-security-policy/allow-privilege-escalation/suite.yaml index 28012235d..1ce8ca9c5 100644 --- a/library/pod-security-policy/allow-privilege-escalation/suite.yaml +++ b/library/pod-security-policy/allow-privilege-escalation/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-allow-privilege-escalation-container/example_disallowed.yaml assertions: - violations: yes + - name: example-disallowed-ephemeral + object: samples/psp-allow-privilege-escalation-container/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/allow-privilege-escalation/template.yaml b/library/pod-security-policy/allow-privilege-escalation/template.yaml index 8c297250b..15040c931 100644 --- a/library/pod-security-policy/allow-privilege-escalation/template.yaml +++ b/library/pod-security-policy/allow-privilege-escalation/template.yaml @@ -58,6 +58,9 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } # has_field returns whether an object has a field has_field(object, field) = true { object[field] diff --git a/library/pod-security-policy/apparmor/samples/psp-apparmor/example_disallowed_ephemeral.yaml b/library/pod-security-policy/apparmor/samples/psp-apparmor/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..cd6fc5f81 --- /dev/null +++ b/library/pod-security-policy/apparmor/samples/psp-apparmor/example_disallowed_ephemeral.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-apparmor-disallowed + annotations: + # apparmor.security.beta.kubernetes.io/pod: unconfined # runtime/default + container.apparmor.security.beta.kubernetes.io/nginx: unconfined + labels: + app: nginx-apparmor +spec: + ephemeralContainers: + - name: nginx + image: nginx diff --git a/library/pod-security-policy/apparmor/suite.yaml b/library/pod-security-policy/apparmor/suite.yaml index 9addb98f0..973eb7adf 100644 --- a/library/pod-security-policy/apparmor/suite.yaml +++ b/library/pod-security-policy/apparmor/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-apparmor/example_disallowed.yaml assertions: - violations: yes + - name: example-disallowed-ephemeral + object: samples/psp-apparmor/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/apparmor/template.yaml b/library/pod-security-policy/apparmor/template.yaml index b79f0fb03..4384d71be 100644 --- a/library/pod-security-policy/apparmor/template.yaml +++ b/library/pod-security-policy/apparmor/template.yaml @@ -63,6 +63,9 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } get_annotation_for(container, metadata) = out { out = metadata.annotations[sprintf("container.apparmor.security.beta.kubernetes.io/%v", [container.name])] diff --git a/library/pod-security-policy/capabilities/samples/capabilities-demo/example_disallowed_ephemeral.yaml b/library/pod-security-policy/capabilities/samples/capabilities-demo/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..5467c826e --- /dev/null +++ b/library/pod-security-policy/capabilities/samples/capabilities-demo/example_disallowed_ephemeral.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + securityContext: + capabilities: + add: ["disallowedcapability"] + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/library/pod-security-policy/capabilities/suite.yaml b/library/pod-security-policy/capabilities/suite.yaml index 6909ec433..f352d11f9 100644 --- a/library/pod-security-policy/capabilities/suite.yaml +++ b/library/pod-security-policy/capabilities/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/capabilities-demo/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/capabilities-demo/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/capabilities/template.yaml b/library/pod-security-policy/capabilities/template.yaml index 2dd513215..6f93c631c 100644 --- a/library/pod-security-policy/capabilities/template.yaml +++ b/library/pod-security-policy/capabilities/template.yaml @@ -81,6 +81,22 @@ spec: } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + has_disallowed_capabilities(container) + msg := sprintf("ephemeral container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) + } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + missing_drop_capabilities(container) + msg := sprintf("ephemeral container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) + } + + has_disallowed_capabilities(container) { allowed := {c | c := lower(input.parameters.allowedCapabilities[_])} not allowed["*"] diff --git a/library/pod-security-policy/host-filesystem/samples/psp-host-filesystem/example_disallowed_ephemeral.yaml b/library/pod-security-policy/host-filesystem/samples/psp-host-filesystem/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..beece55c0 --- /dev/null +++ b/library/pod-security-policy/host-filesystem/samples/psp-host-filesystem/example_disallowed_ephemeral.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-filesystem + labels: + app: nginx-host-filesystem-disallowed +spec: + ephemeralContainers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + readOnly: true + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host diff --git a/library/pod-security-policy/host-filesystem/suite.yaml b/library/pod-security-policy/host-filesystem/suite.yaml index f97357467..fdf9321d1 100644 --- a/library/pod-security-policy/host-filesystem/suite.yaml +++ b/library/pod-security-policy/host-filesystem/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-host-filesystem/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-host-filesystem/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/host-filesystem/template.yaml b/library/pod-security-policy/host-filesystem/template.yaml index 4c54934f3..ca18b9fdf 100644 --- a/library/pod-security-policy/host-filesystem/template.yaml +++ b/library/pod-security-policy/host-filesystem/template.yaml @@ -128,3 +128,7 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } diff --git a/library/pod-security-policy/host-network-ports/samples/psp-host-network-ports/example_disallowed_ephemeral.yaml b/library/pod-security-policy/host-network-ports/samples/psp-host-network-ports/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..7a4fa3114 --- /dev/null +++ b/library/pod-security-policy/host-network-ports/samples/psp-host-network-ports/example_disallowed_ephemeral.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-networking-ports-disallowed + labels: + app: nginx-host-networking-ports +spec: + hostNetwork: true + ephemeralContainers: + - name: nginx + image: nginx + ports: + - containerPort: 9001 + hostPort: 9001 diff --git a/library/pod-security-policy/host-network-ports/suite.yaml b/library/pod-security-policy/host-network-ports/suite.yaml index cdbe68315..75cf7b805 100644 --- a/library/pod-security-policy/host-network-ports/suite.yaml +++ b/library/pod-security-policy/host-network-ports/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-host-network-ports/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-host-network-ports/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/host-network-ports/template.yaml b/library/pod-security-policy/host-network-ports/template.yaml index 9d2ff9dce..5d15e00aa 100644 --- a/library/pod-security-policy/host-network-ports/template.yaml +++ b/library/pod-security-policy/host-network-ports/template.yaml @@ -78,6 +78,11 @@ spec: c := input.review.object.spec.initContainers[_] not is_exempt(c) } + + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + not is_exempt(c) + } libs: - | package lib.exempt_container diff --git a/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/example_disallowed_ephemeral.yaml b/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..e8c8b9945 --- /dev/null +++ b/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/example_disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-privileged-disallowed + labels: + app: nginx-privileged +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + privileged: true diff --git a/library/pod-security-policy/privileged-containers/suite.yaml b/library/pod-security-policy/privileged-containers/suite.yaml index ad3784ef4..aa014860e 100644 --- a/library/pod-security-policy/privileged-containers/suite.yaml +++ b/library/pod-security-policy/privileged-containers/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-privileged-container/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-privileged-container/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/privileged-containers/template.yaml b/library/pod-security-policy/privileged-containers/template.yaml index 0ac1123c2..36eadf815 100644 --- a/library/pod-security-policy/privileged-containers/template.yaml +++ b/library/pod-security-policy/privileged-containers/template.yaml @@ -53,6 +53,10 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } libs: - | package lib.exempt_container diff --git a/library/pod-security-policy/proc-mount/samples/psp-proc-mount/example_disallowed_ephemeral.yaml b/library/pod-security-policy/proc-mount/samples/psp-proc-mount/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..4be38f45d --- /dev/null +++ b/library/pod-security-policy/proc-mount/samples/psp-proc-mount/example_disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-proc-mount-disallowed + labels: + app: nginx-proc-mount +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + procMount: Unmasked #Default diff --git a/library/pod-security-policy/proc-mount/suite.yaml b/library/pod-security-policy/proc-mount/suite.yaml index 12e40462b..caf5d5981 100644 --- a/library/pod-security-policy/proc-mount/suite.yaml +++ b/library/pod-security-policy/proc-mount/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-proc-mount/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-proc-mount/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/proc-mount/template.yaml b/library/pod-security-policy/proc-mount/template.yaml index 5f9dd0291..192a7f6f3 100644 --- a/library/pod-security-policy/proc-mount/template.yaml +++ b/library/pod-security-policy/proc-mount/template.yaml @@ -74,6 +74,10 @@ spec: c := input.review.object.spec.initContainers[_] c.securityContext.procMount } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + c.securityContext.procMount + } get_allowed_proc_mount(arg) = out { not arg.parameters diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_disallowed_ephemeral.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..d0ce2c4dc --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + readOnlyRootFilesystem: false diff --git a/library/pod-security-policy/read-only-root-filesystem/suite.yaml b/library/pod-security-policy/read-only-root-filesystem/suite.yaml index 467913b09..1b0a65177 100644 --- a/library/pod-security-policy/read-only-root-filesystem/suite.yaml +++ b/library/pod-security-policy/read-only-root-filesystem/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-readonlyrootfilesystem/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-readonlyrootfilesystem/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/read-only-root-filesystem/template.yaml b/library/pod-security-policy/read-only-root-filesystem/template.yaml index 74ff879fa..6e8ade4d6 100644 --- a/library/pod-security-policy/read-only-root-filesystem/template.yaml +++ b/library/pod-security-policy/read-only-root-filesystem/template.yaml @@ -60,6 +60,9 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } # has_field returns whether an object has a field has_field(object, field) = true { diff --git a/library/pod-security-policy/seccomp/samples/psp-seccomp/example_disallowed_ephemeral.yaml b/library/pod-security-policy/seccomp/samples/psp-seccomp/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..1555d700e --- /dev/null +++ b/library/pod-security-policy/seccomp/samples/psp-seccomp/example_disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-disallowed + annotations: + container.seccomp.security.alpha.kubernetes.io/nginx: unconfined + labels: + app: nginx-seccomp +spec: + ephemeralContainers: + - name: nginx + image: nginx diff --git a/library/pod-security-policy/seccomp/suite.yaml b/library/pod-security-policy/seccomp/suite.yaml index 7c27b3bd3..b3abd6371 100644 --- a/library/pod-security-policy/seccomp/suite.yaml +++ b/library/pod-security-policy/seccomp/suite.yaml @@ -25,3 +25,8 @@ tests: object: samples/psp-seccomp/example_allowed2.yaml assertions: - violations: no + - name: example-disallowed-container-ephemeral + object: samples/psp-seccomp/example_disallowed_ephemeral.yaml + assertions: + - violations: 1 + message: "Seccomp profile 'unconfined' is not allowed for container 'nginx'. Found at: annotation container.seccomp.security.alpha.kubernetes.io/nginx" diff --git a/library/pod-security-policy/seccomp/template.yaml b/library/pod-security-policy/seccomp/template.yaml index 0068025f9..c6ad86428 100644 --- a/library/pod-security-policy/seccomp/template.yaml +++ b/library/pod-security-policy/seccomp/template.yaml @@ -252,6 +252,10 @@ spec: input_containers[container.name] = container { container := input.review.object.spec.initContainers[_] } + + input_containers[container.name] = container { + container := input.review.object.spec.ephemeralContainers[_] + } libs: - | package lib.exempt_container diff --git a/library/pod-security-policy/selinux/samples/psp-selinux-v2/example_disallowed_ephemeral.yaml b/library/pod-security-policy/selinux/samples/psp-selinux-v2/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..3a35fc737 --- /dev/null +++ b/library/pod-security-policy/selinux/samples/psp-selinux-v2/example_disallowed_ephemeral.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-selinux-disallowed + labels: + app: nginx-selinux +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + seLinuxOptions: + level: s1:c234,c567 + user: sysadm_u + role: sysadm_r + type: svirt_lxc_net_t diff --git a/library/pod-security-policy/selinux/suite.yaml b/library/pod-security-policy/selinux/suite.yaml index 57ca55e1f..84534c41d 100644 --- a/library/pod-security-policy/selinux/suite.yaml +++ b/library/pod-security-policy/selinux/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-selinux-v2/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-selinux-v2/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/selinux/template.yaml b/library/pod-security-policy/selinux/template.yaml index 0d8ebf217..1adf7760d 100644 --- a/library/pod-security-policy/selinux/template.yaml +++ b/library/pod-security-policy/selinux/template.yaml @@ -97,6 +97,10 @@ spec: c := input.review.object.spec.initContainers[_] has_field(c.securityContext, "seLinuxOptions") } + input_security_context[c] { + c := input.review.object.spec.ephemeralContainers[_] + has_field(c.securityContext, "seLinuxOptions") + } # has_field returns whether an object has a field has_field(object, field) = true { diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed_ephemeral.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed_ephemeral.yaml new file mode 100644 index 000000000..6297f0dfd --- /dev/null +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed_ephemeral.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-disallowed + labels: + app: nginx-users +spec: + securityContext: + supplementalGroups: + - 250 + fsGroup: 250 + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 diff --git a/library/pod-security-policy/users/suite.yaml b/library/pod-security-policy/users/suite.yaml index fbf869880..502d79d61 100644 --- a/library/pod-security-policy/users/suite.yaml +++ b/library/pod-security-policy/users/suite.yaml @@ -15,3 +15,7 @@ tests: object: samples/psp-pods-allowed-user-ranges/example_allowed.yaml assertions: - violations: no + - name: example-disallowed-ephemeral + object: samples/psp-pods-allowed-user-ranges/example_disallowed_ephemeral.yaml + assertions: + - violations: yes diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 303af13e5..2284afe4f 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -254,6 +254,9 @@ spec: input_containers[c] { c := input.review.object.spec.initContainers[_] } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + } libs: - | package lib.exempt_container diff --git a/mutation/pod-security-policy/allow-privilege-escalation/samples/mutation.yaml b/mutation/pod-security-policy/allow-privilege-escalation/samples/mutation.yaml index 54c860cfe..9c84b4f95 100644 --- a/mutation/pod-security-policy/allow-privilege-escalation/samples/mutation.yaml +++ b/mutation/pod-security-policy/allow-privilege-escalation/samples/mutation.yaml @@ -31,3 +31,20 @@ spec: condition: MustNotExist assign: value: false +--- +apiVersion: mutations.gatekeeper.sh/v1alpha1 +kind: Assign +metadata: + name: k8spspdefaultallowprivilegeescalation-ephemeral +spec: + applyTo: + - groups: [""] + kinds: ["Pod"] + versions: ["v1"] + location: "spec.ephemeralContainers[name:*].securityContext.allowPrivilegeEscalation" + parameters: + pathTests: + - subPath: "spec.ephemeralContainers[name:*].securityContext.allowPrivilegeEscalation" + condition: MustNotExist + assign: + value: false diff --git a/src/general/allowedrepos/src.rego b/src/general/allowedrepos/src.rego index a925e9e9c..649dafb77 100644 --- a/src/general/allowedrepos/src.rego +++ b/src/general/allowedrepos/src.rego @@ -13,3 +13,10 @@ violation[{"msg": msg}] { not any(satisfied) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } + +violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] + not any(satisfied) + msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) +} diff --git a/src/general/automount-serviceaccount-token/src.rego b/src/general/automount-serviceaccount-token/src.rego index 581237d24..88fd1aec9 100644 --- a/src/general/automount-serviceaccount-token/src.rego +++ b/src/general/automount-serviceaccount-token/src.rego @@ -25,6 +25,8 @@ input_containers[c] { c := input.review.object.spec.initContainers[_] } +# Ephemeral containers not checked as it is not possible to set field. + has_key(x, k) { _ = x[k] } diff --git a/src/general/containerlimits/src.rego b/src/general/containerlimits/src.rego index 752428348..9124c886b 100644 --- a/src/general/containerlimits/src.rego +++ b/src/general/containerlimits/src.rego @@ -133,6 +133,8 @@ violation[{"msg": msg}] { general_violation[{"msg": msg, "field": "initContainers"}] } +# Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/src/general/containerrequests/src.rego b/src/general/containerrequests/src.rego index ae2791442..79e1e65ab 100644 --- a/src/general/containerrequests/src.rego +++ b/src/general/containerrequests/src.rego @@ -133,6 +133,8 @@ violation[{"msg": msg}] { general_violation[{"msg": msg, "field": "initContainers"}] } +# Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/src/general/containerresourceratios/src.rego b/src/general/containerresourceratios/src.rego index ce451a136..a31366235 100644 --- a/src/general/containerresourceratios/src.rego +++ b/src/general/containerresourceratios/src.rego @@ -140,6 +140,8 @@ violation[{"msg": msg}] { general_violation[{"msg": msg, "field": "initContainers"}] } +# Ephemeral containers not checked as it is not possible to set field. + general_violation[{"msg": msg, "field": field}] { container := input.review.object.spec[field][_] not is_exempt(container) diff --git a/src/general/disallowedtags/src.rego b/src/general/disallowedtags/src.rego index 3b5bd101e..d35964fd7 100644 --- a/src/general/disallowedtags/src.rego +++ b/src/general/disallowedtags/src.rego @@ -24,3 +24,6 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} diff --git a/src/general/imagedigests/src.rego b/src/general/imagedigests/src.rego index b90096182..a1fdd3836 100644 --- a/src/general/imagedigests/src.rego +++ b/src/general/imagedigests/src.rego @@ -17,3 +17,11 @@ violation[{"msg": msg}] { not all(satisfied) msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } + +violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] + not all(satisfied) + msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) +} diff --git a/src/pod-security-policy/allow-privilege-escalation/src.rego b/src/pod-security-policy/allow-privilege-escalation/src.rego index b9bc23474..7c16226c1 100644 --- a/src/pod-security-policy/allow-privilege-escalation/src.rego +++ b/src/pod-security-policy/allow-privilege-escalation/src.rego @@ -21,6 +21,9 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} # has_field returns whether an object has a field has_field(object, field) = true { object[field] diff --git a/src/pod-security-policy/apparmor/src.rego b/src/pod-security-policy/apparmor/src.rego index 5bde51445..613df8030 100644 --- a/src/pod-security-policy/apparmor/src.rego +++ b/src/pod-security-policy/apparmor/src.rego @@ -20,6 +20,9 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} get_annotation_for(container, metadata) = out { out = metadata.annotations[sprintf("container.apparmor.security.beta.kubernetes.io/%v", [container.name])] diff --git a/src/pod-security-policy/capabilities/src.rego b/src/pod-security-policy/capabilities/src.rego index c04c490c3..95e4fb529 100644 --- a/src/pod-security-policy/capabilities/src.rego +++ b/src/pod-security-policy/capabilities/src.rego @@ -33,6 +33,22 @@ violation[{"msg": msg}] { } + +violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + has_disallowed_capabilities(container) + msg := sprintf("ephemeral container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) +} + +violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + missing_drop_capabilities(container) + msg := sprintf("ephemeral container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) +} + + has_disallowed_capabilities(container) { allowed := {c | c := lower(input.parameters.allowedCapabilities[_])} not allowed["*"] diff --git a/src/pod-security-policy/host-filesystem/src.rego b/src/pod-security-policy/host-filesystem/src.rego index f14b96bc7..3e5ab3b8d 100644 --- a/src/pod-security-policy/host-filesystem/src.rego +++ b/src/pod-security-policy/host-filesystem/src.rego @@ -88,3 +88,7 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } + +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} diff --git a/src/pod-security-policy/host-network-ports/src.rego b/src/pod-security-policy/host-network-ports/src.rego index c78702e32..bc5b5b0e7 100644 --- a/src/pod-security-policy/host-network-ports/src.rego +++ b/src/pod-security-policy/host-network-ports/src.rego @@ -31,3 +31,8 @@ input_containers[c] { c := input.review.object.spec.initContainers[_] not is_exempt(c) } + +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + not is_exempt(c) +} diff --git a/src/pod-security-policy/privileged-containers/src.rego b/src/pod-security-policy/privileged-containers/src.rego index 8fad521e1..facc61eff 100644 --- a/src/pod-security-policy/privileged-containers/src.rego +++ b/src/pod-security-policy/privileged-containers/src.rego @@ -16,3 +16,7 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } + +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} diff --git a/src/pod-security-policy/proc-mount/src.rego b/src/pod-security-policy/proc-mount/src.rego index fb8f68656..7f23dd783 100644 --- a/src/pod-security-policy/proc-mount/src.rego +++ b/src/pod-security-policy/proc-mount/src.rego @@ -26,6 +26,10 @@ input_containers[c] { c := input.review.object.spec.initContainers[_] c.securityContext.procMount } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + c.securityContext.procMount +} get_allowed_proc_mount(arg) = out { not arg.parameters diff --git a/src/pod-security-policy/read-only-root-filesystem/src.rego b/src/pod-security-policy/read-only-root-filesystem/src.rego index 059de03d8..084051e6b 100644 --- a/src/pod-security-policy/read-only-root-filesystem/src.rego +++ b/src/pod-security-policy/read-only-root-filesystem/src.rego @@ -22,6 +22,9 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +} # has_field returns whether an object has a field has_field(object, field) = true { diff --git a/src/pod-security-policy/seccomp/src.rego b/src/pod-security-policy/seccomp/src.rego index feeff5495..53355d31a 100644 --- a/src/pod-security-policy/seccomp/src.rego +++ b/src/pod-security-policy/seccomp/src.rego @@ -184,3 +184,7 @@ input_containers[container.name] = container { input_containers[container.name] = container { container := input.review.object.spec.initContainers[_] } + +input_containers[container.name] = container { + container := input.review.object.spec.ephemeralContainers[_] +} diff --git a/src/pod-security-policy/selinux/src.rego b/src/pod-security-policy/selinux/src.rego index acabdc6c2..b9e98ede6 100644 --- a/src/pod-security-policy/selinux/src.rego +++ b/src/pod-security-policy/selinux/src.rego @@ -40,6 +40,10 @@ input_security_context[c] { c := input.review.object.spec.initContainers[_] has_field(c.securityContext, "seLinuxOptions") } +input_security_context[c] { + c := input.review.object.spec.ephemeralContainers[_] + has_field(c.securityContext, "seLinuxOptions") +} # has_field returns whether an object has a field has_field(object, field) = true { diff --git a/src/pod-security-policy/users/src.rego b/src/pod-security-policy/users/src.rego index a804e13fe..6f0b4f4d0 100644 --- a/src/pod-security-policy/users/src.rego +++ b/src/pod-security-policy/users/src.rego @@ -121,3 +121,6 @@ input_containers[c] { input_containers[c] { c := input.review.object.spec.initContainers[_] } +input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] +}