From 929ae06bf6c67694a25ae2902ebab642a79300e9 Mon Sep 17 00:00:00 2001 From: juliankatz Date: Mon, 26 Aug 2024 15:42:27 -0700 Subject: [PATCH] fix(k8spspreadonlyrootfilesystem): CEL support wildcard in exemptImages Despite it being non-sensical to put a `*` in exemptImages (functionally disabling the policy), this is supported in the existing rego implementation of the template. Thus, not doing it in the CEL implementation is an inconsistency and a breaking change. This PR upholds the contract by adding support for `*` as an exemptImage. Signed-off-by: juliankatz --- .../1.1.1/artifacthub-pkg.yml | 22 +++ .../1.1.1/kustomization.yaml | 2 + .../constraint.yaml | 12 ++ .../disallowed_ephemeral.yaml | 12 ++ .../example_allowed.yaml | 12 ++ .../example_allowed_exempted.yaml | 12 ++ .../example_disallowed.yaml | 12 ++ .../psp-readonlyrootfilesystem/update.yaml | 17 ++ .../samples/wildcard-support/constraint.yaml | 12 ++ .../example_safe_image_prefix.yaml | 12 ++ .../example_unsafe_image_prefix.yaml | 12 ++ .../full_wildcard_constraint.yaml | 12 ++ .../prefix_matching_constraint.yaml | 12 ++ .../1.1.1/suite.yaml | 51 +++++ .../1.1.1/template.yaml | 140 ++++++++++++++ .../constraint.yaml | 3 + .../example_allowed_exempted.yaml | 12 ++ .../example_safe_image_prefix.yaml | 12 ++ .../example_unsafe_image_prefix.yaml | 12 ++ .../full_wildcard_constraint.yaml | 12 ++ .../prefix_matching_constraint.yaml | 12 ++ .../read-only-root-filesystem/suite.yaml | 24 +++ .../read-only-root-filesystem/template.yaml | 4 +- .../read-only-root-filesystem/constraint.tmpl | 2 +- .../read-only-root-filesystem/src.cel | 2 +- .../validation/read-only-root-filesystem.md | 175 +++++++++++++++++- 26 files changed, 616 insertions(+), 6 deletions(-) create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/update.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard-support/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_safe_image_prefix.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_unsafe_image_prefix.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/full_wildcard_constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/prefix_matching_constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/template.yaml create mode 100644 library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml create mode 100644 library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_safe_image_prefix.yaml create mode 100644 library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_unsafe_image_prefix.yaml create mode 100644 library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/full_wildcard_constraint.yaml create mode 100644 library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/prefix_matching_constraint.yaml diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/artifacthub-pkg.yml new file mode 100644 index 0000000000..05b0b5ab60 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.1.1 +name: k8spspreadonlyrootfilesystem +displayName: Read Only Root Filesystem +createdAt: "2024-08-26T22:42:23Z" +description: Requires the use of a read-only root file system by pod containers. Corresponds to the `readOnlyRootFilesystem` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +digest: 9ec2743dce71b385161873179a1d70b6f801f72b077bd178334f75f2ee1023bd +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/read-only-root-filesystem +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Read Only Root Filesystem + Requires the use of a read-only root file system by pod containers. Corresponds to the `readOnlyRootFilesystem` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/kustomization.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/kustomization.yaml new file mode 100644 index 0000000000..7d70d11b71 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/constraint.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/constraint.yaml new file mode 100644 index 0000000000..d32dc33ab7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "specialprogram" diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/disallowed_ephemeral.yaml new file mode 100644 index 0000000000..d0ce2c4dc5 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/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/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed.yaml new file mode 100644 index 0000000000..9c96bd18cd --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: nginx + securityContext: + readOnlyRootFilesystem: true diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml new file mode 100644 index 0000000000..1f86b59aed --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: specialprogram + image: specialprogram + securityContext: + readOnlyRootFilesystem: false diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_disallowed.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_disallowed.yaml new file mode 100644 index 0000000000..7571bfd9fb --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/example_disallowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: nginx + securityContext: + readOnlyRootFilesystem: false diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/update.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/update.yaml new file mode 100644 index 0000000000..b31ae5e3a8 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/psp-readonlyrootfilesystem/update.yaml @@ -0,0 +1,17 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem + spec: + containers: + - name: nginx + image: nginx + securityContext: + readOnlyRootFilesystem: false diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard-support/constraint.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard-support/constraint.yaml new file mode 100644 index 0000000000..b5497e7611 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard-support/constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "*" diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_safe_image_prefix.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_safe_image_prefix.yaml new file mode 100644 index 0000000000..6c4c60d104 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_safe_image_prefix.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "safe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_unsafe_image_prefix.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_unsafe_image_prefix.yaml new file mode 100644 index 0000000000..563abb05f7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/example_unsafe_image_prefix.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "unsafe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/full_wildcard_constraint.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/full_wildcard_constraint.yaml new file mode 100644 index 0000000000..b5497e7611 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/full_wildcard_constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "*" diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/prefix_matching_constraint.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/prefix_matching_constraint.yaml new file mode 100644 index 0000000000..8bac931409 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/samples/wildcard_support/prefix_matching_constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "safe-images.com/*" diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/suite.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/suite.yaml new file mode 100644 index 0000000000..cd4fb208a0 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/suite.yaml @@ -0,0 +1,51 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: read-only-root-filesystem +tests: +- name: require-read-only-root-filesystem + template: template.yaml + constraint: samples/psp-readonlyrootfilesystem/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-readonlyrootfilesystem/example_disallowed.yaml + assertions: + - violations: yes + message: "only read-only root filesystem container is allowed: nginx" + - name: example-allowed + object: samples/psp-readonlyrootfilesystem/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-readonlyrootfilesystem/disallowed_ephemeral.yaml + assertions: + - violations: yes + message: "only read-only root filesystem container is allowed: nginx" + - name: update + object: samples/psp-readonlyrootfilesystem/update.yaml + assertions: + - violations: no + - name: exact exemption + object: samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml + assertions: + - violations: no +- name: full-wildcard + template: template.yaml + constraint: samples/wildcard_support/full_wildcard_constraint.yaml + cases: + - name: allow-normally-disallowed + object: samples/psp-readonlyrootfilesystem/example_disallowed.yaml + assertions: + - violations: no +- name: wildcard-suffix + template: template.yaml + constraint: samples/wildcard_support/prefix_matching_constraint.yaml + cases: + - name: image-with-exempt-prefix-readOnlyRootFilesystem-not-required + object: samples/wildcard_support/example_safe_image_prefix.yaml + assertions: + - violations: no + - name: image-with-different-prefix-must-set-readOnlyRootFilesystem + object: samples/wildcard_support/example_unsafe_image_prefix.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/template.yaml b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/template.yaml new file mode 100644 index 0000000000..7f3a402e80 --- /dev/null +++ b/artifacthub/library/pod-security-policy/read-only-root-filesystem/1.1.1/template.yaml @@ -0,0 +1,140 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspreadonlyrootfilesystem + annotations: + metadata.gatekeeper.sh/title: "Read Only Root Filesystem" + metadata.gatekeeper.sh/version: 1.1.1 + description: >- + Requires the use of a read-only root file system by pod containers. + Corresponds to the `readOnlyRootFilesystem` field in a + PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +spec: + crd: + spec: + names: + kind: K8sPSPReadOnlyRootFilesystem + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Requires the use of a read-only root file system by pod containers. + Corresponds to the `readOnlyRootFilesystem` field in a + PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + properties: + exemptImages: + description: >- + Any container that uses an image that matches an entry in this list will be excluded + from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`. + + It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name) + in order to avoid unexpectedly exempting images from an untrusted repository. + type: array + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + code: + - engine: K8sNativeValidation + source: + variables: + - name: containers + expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' + - name: initContainers + expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' + - name: ephemeralContainers + expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' + - name: exemptImagePrefixes + expression: | + !has(variables.params.exemptImages) ? [] : + variables.params.exemptImages.filter(image, image.endsWith("*")).map(image, string(image).replace("*", "")) + - name: exemptImageExplicit + expression: | + !has(variables.params.exemptImages) ? [] : + variables.params.exemptImages.filter(image, !image.endsWith("*")) + - name: exemptImages + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + container.image in variables.exemptImageExplicit || + variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))).map(container, container.image) + - name: badContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + !(container.image in variables.exemptImages) && + (!has(container.securityContext) || + !has(container.securityContext.readOnlyRootFilesystem) || + container.securityContext.readOnlyRootFilesystem != true) + ).map(container, container.name) + validations: + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.badContainers) == 0' + messageExpression: '"only read-only root filesystem container is allowed: " + variables.badContainers.join(", ")' + + - engine: Rego + source: + rego: | + package k8spspreadonlyrootfilesystem + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg, "details": {}}] { + # spec.containers.readOnlyRootFilesystem field is immutable. + not is_update(input.review) + + c := input_containers[_] + not is_exempt(c) + input_read_only_root_fs(c) + msg := sprintf("only read-only root filesystem container is allowed: %v", [c.name]) + } + + input_read_only_root_fs(c) { + not has_field(c, "securityContext") + } + input_read_only_root_fs(c) { + not c.securityContext.readOnlyRootFilesystem == true + } + + input_containers[c] { + c := input.review.object.spec.containers[_] + } + 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] + } + libs: + - | + package lib.exclude_update + + is_update(review) { + review.operation == "UPDATE" + } + - | + package lib.exempt_container + + is_exempt(container) { + exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", []) + img := container.image + exemption := exempt_images[_] + _matches_exemption(img, exemption) + } + + _matches_exemption(img, exemption) { + not endswith(exemption, "*") + exemption == img + } + + _matches_exemption(img, exemption) { + endswith(exemption, "*") + prefix := trim_suffix(exemption, "*") + startswith(img, prefix) + } diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/constraint.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/constraint.yaml index 66d6bdabe9..d32dc33ab7 100644 --- a/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/constraint.yaml +++ b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/constraint.yaml @@ -7,3 +7,6 @@ spec: kinds: - apiGroups: [""] kinds: ["Pod"] + parameters: + exemptImages: + - "specialprogram" diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml new file mode 100644 index 0000000000..1f86b59aed --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: specialprogram + image: specialprogram + securityContext: + readOnlyRootFilesystem: false diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_safe_image_prefix.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_safe_image_prefix.yaml new file mode 100644 index 0000000000..6c4c60d104 --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_safe_image_prefix.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "safe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_unsafe_image_prefix.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_unsafe_image_prefix.yaml new file mode 100644 index 0000000000..563abb05f7 --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_unsafe_image_prefix.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "unsafe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/full_wildcard_constraint.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/full_wildcard_constraint.yaml new file mode 100644 index 0000000000..b5497e7611 --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/full_wildcard_constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "*" diff --git a/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/prefix_matching_constraint.yaml b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/prefix_matching_constraint.yaml new file mode 100644 index 0000000000..8bac931409 --- /dev/null +++ b/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/prefix_matching_constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "safe-images.com/*" 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 fb52faa007..cd4fb208a0 100644 --- a/library/pod-security-policy/read-only-root-filesystem/suite.yaml +++ b/library/pod-security-policy/read-only-root-filesystem/suite.yaml @@ -25,3 +25,27 @@ tests: object: samples/psp-readonlyrootfilesystem/update.yaml assertions: - violations: no + - name: exact exemption + object: samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml + assertions: + - violations: no +- name: full-wildcard + template: template.yaml + constraint: samples/wildcard_support/full_wildcard_constraint.yaml + cases: + - name: allow-normally-disallowed + object: samples/psp-readonlyrootfilesystem/example_disallowed.yaml + assertions: + - violations: no +- name: wildcard-suffix + template: template.yaml + constraint: samples/wildcard_support/prefix_matching_constraint.yaml + cases: + - name: image-with-exempt-prefix-readOnlyRootFilesystem-not-required + object: samples/wildcard_support/example_safe_image_prefix.yaml + assertions: + - violations: no + - name: image-with-different-prefix-must-set-readOnlyRootFilesystem + object: samples/wildcard_support/example_unsafe_image_prefix.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 361ff999d5..7f3a402e80 100644 --- a/library/pod-security-policy/read-only-root-filesystem/template.yaml +++ b/library/pod-security-policy/read-only-root-filesystem/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspreadonlyrootfilesystem annotations: metadata.gatekeeper.sh/title: "Read Only Root Filesystem" - metadata.gatekeeper.sh/version: 1.1.0 + metadata.gatekeeper.sh/version: 1.1.1 description: >- Requires the use of a read-only root file system by pod containers. Corresponds to the `readOnlyRootFilesystem` field in a @@ -59,7 +59,7 @@ spec: expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || - variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) + variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))).map(container, container.image) - name: badContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, diff --git a/src/pod-security-policy/read-only-root-filesystem/constraint.tmpl b/src/pod-security-policy/read-only-root-filesystem/constraint.tmpl index 862dfa51cd..57516f3d88 100644 --- a/src/pod-security-policy/read-only-root-filesystem/constraint.tmpl +++ b/src/pod-security-policy/read-only-root-filesystem/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspreadonlyrootfilesystem annotations: metadata.gatekeeper.sh/title: "Read Only Root Filesystem" - metadata.gatekeeper.sh/version: 1.1.0 + metadata.gatekeeper.sh/version: 1.1.1 description: >- Requires the use of a read-only root file system by pod containers. Corresponds to the `readOnlyRootFilesystem` field in a diff --git a/src/pod-security-policy/read-only-root-filesystem/src.cel b/src/pod-security-policy/read-only-root-filesystem/src.cel index 0c4db172b4..0be247c12a 100644 --- a/src/pod-security-policy/read-only-root-filesystem/src.cel +++ b/src/pod-security-policy/read-only-root-filesystem/src.cel @@ -17,7 +17,7 @@ variables: expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || - variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) + variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))).map(container, container.image) - name: badContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, diff --git a/website/docs/validation/read-only-root-filesystem.md b/website/docs/validation/read-only-root-filesystem.md index 038698b2ae..6cb4fa0c02 100644 --- a/website/docs/validation/read-only-root-filesystem.md +++ b/website/docs/validation/read-only-root-filesystem.md @@ -16,7 +16,7 @@ metadata: name: k8spspreadonlyrootfilesystem annotations: metadata.gatekeeper.sh/title: "Read Only Root Filesystem" - metadata.gatekeeper.sh/version: 1.1.0 + metadata.gatekeeper.sh/version: 1.1.1 description: >- Requires the use of a read-only root file system by pod containers. Corresponds to the `readOnlyRootFilesystem` field in a @@ -71,7 +71,7 @@ spec: expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || - variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) + variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))).map(container, container.image) - name: badContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, @@ -174,6 +174,9 @@ spec: kinds: - apiGroups: [""] kinds: ["Pod"] + parameters: + exemptImages: + - "specialprogram" ``` @@ -262,6 +265,174 @@ Usage kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/disallowed_ephemeral.yaml ``` + +
+exact exemption + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: specialprogram + image: specialprogram + securityContext: + readOnlyRootFilesystem: false + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_allowed_exempted.yaml +``` + +
+ + +
+full-wildcard + +
+constraint + +```yaml +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "*" + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/full_wildcard_constraint.yaml +``` + +
+ +
+allow-normally-disallowed + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-disallowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: nginx + securityContext: + readOnlyRootFilesystem: false + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/psp-readonlyrootfilesystem/example_disallowed.yaml +``` + +
+ + +
+wildcard-suffix + +
+constraint + +```yaml +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPReadOnlyRootFilesystem +metadata: + name: psp-readonlyrootfilesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + exemptImages: + - "safe-images.com/*" + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/prefix_matching_constraint.yaml +``` + +
+ +
+image-with-exempt-prefix-readOnlyRootFilesystem-not-required + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "safe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_safe_image_prefix.yaml +``` + +
+
+image-with-different-prefix-must-set-readOnlyRootFilesystem + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx-readonlyrootfilesystem-allowed + labels: + app: nginx-readonlyrootfilesystem +spec: + containers: + - name: nginx + image: "unsafe-images.com/nginx" + securityContext: + readOnlyRootFilesystem: false + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/read-only-root-filesystem/samples/wildcard_support/example_unsafe_image_prefix.yaml +``` +