From 975a68ad0ffd5ecfcb3647960be3cf808c7c52ee Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Thu, 30 May 2024 00:08:45 +0000 Subject: [PATCH 01/12] adding psp-users CEL policy Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 22 + .../users/1.1.0/kustomization.yaml | 2 + .../constraint.yaml | 30 ++ .../disallowed_ephemeral.yaml | 17 + .../example_allowed.yaml | 17 + .../example_disallowed.yaml | 17 + .../psp-pods-allowed-user-ranges/update.yaml | 22 + .../users/1.1.0/suite.yaml | 25 + .../users/1.1.0/template.yaml | 472 +++++++++++++++++ .../constraint.yaml | 2 +- .../pod-security-policy/users/template.yaml | 439 +++++++++++----- src/pod-security-policy/users/constraint.tmpl | 22 +- src/pod-security-policy/users/src.cel | 178 +++++++ website/docs/validation/users.md | 497 ++++++++++++------ 14 files changed, 1468 insertions(+), 294 deletions(-) create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/update.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/template.yaml create mode 100644 src/pod-security-policy/users/src.cel diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml new file mode 100644 index 000000000..d4a7dcf71 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.1.0 +name: k8spspallowedusers +displayName: Allowed Users +createdAt: "2024-05-30T00:06:50Z" +description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups +digest: 5d2cc4fd33ea1151f64adb0376d3164e93bea5bdfcc39449a93342d6209d3672 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Allowed Users + Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/kustomization.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml new file mode 100644 index 000000000..37f88d63b --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -0,0 +1,30 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPAllowedUsers +metadata: + name: psp-pods-allowed-user-ranges +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + runAsUser: + rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny + ranges: + - min: 100 + max: 200 + runAsGroup: + rule: MustRunAs # MayRunAs # RunAsAny + ranges: + - min: 100 + max: 200 + supplementalGroups: + rule: MustRunAs # MayRunAs # RunAsAny + ranges: + - min: 100 + max: 200 + fsGroup: + rule: MustRunAs # MayRunAs # RunAsAny + ranges: + - min: 100 + max: 200 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml new file mode 100644 index 000000000..6297f0dfd --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/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/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed.yaml new file mode 100644 index 000000000..79899ed98 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-allowed + labels: + app: nginx-users +spec: + securityContext: + supplementalGroups: + - 199 + fsGroup: 199 + containers: + - name: nginx + image: nginx + securityContext: + runAsUser: 199 + runAsGroup: 199 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml new file mode 100644 index 000000000..516cce14b --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-disallowed + labels: + app: nginx-users +spec: + securityContext: + supplementalGroups: + - 250 + fsGroup: 250 + containers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/update.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/update.yaml new file mode 100644 index 000000000..6f4d3ed72 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/update.yaml @@ -0,0 +1,22 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-users-disallowed + labels: + app: nginx-users + spec: + securityContext: + supplementalGroups: + - 250 + fsGroup: 250 + containers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml new file mode 100644 index 000000000..5c6e49640 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: users +tests: +- name: users-and-groups-together + template: template.yaml + constraint: samples/psp-pods-allowed-user-ranges/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-pods-allowed-user-ranges/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-pods-allowed-user-ranges/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/psp-pods-allowed-user-ranges/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml new file mode 100644 index 000000000..ceee1dc79 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -0,0 +1,472 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspallowedusers + annotations: + metadata.gatekeeper.sh/title: "Allowed Users" + metadata.gatekeeper.sh/version: 1.1.0 + description: >- + Controls the user and group IDs of the container and some volumes. + Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and + `fsGroup` fields in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups +spec: + crd: + spec: + names: + kind: K8sPSPAllowedUsers + validation: + openAPIV3Schema: + type: object + description: >- + Controls the user and group IDs of the container and some volumes. + Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and + `fsGroup` fields in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups + 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 + runAsUser: + type: object + description: "Controls which user ID values are allowed in a Pod or container-level SecurityContext." + properties: + rule: + type: string + description: "A strategy for applying the runAsUser restriction." + enum: + - MustRunAs + - MustRunAsNonRoot + - RunAsAny + ranges: + type: array + description: "A list of user ID ranges affected by the rule." + items: + type: object + description: "The range of user IDs affected by the rule." + properties: + min: + type: integer + description: "The minimum user ID in the range, inclusive." + max: + type: integer + description: "The maximum user ID in the range, inclusive." + runAsGroup: + type: object + description: "Controls which group ID values are allowed in a Pod or container-level SecurityContext." + properties: + rule: + type: string + description: "A strategy for applying the runAsGroup restriction." + enum: + - MustRunAs + - MayRunAs + - RunAsAny + ranges: + type: array + description: "A list of group ID ranges affected by the rule." + items: + type: object + description: "The range of group IDs affected by the rule." + properties: + min: + type: integer + description: "The minimum group ID in the range, inclusive." + max: + type: integer + description: "The maximum group ID in the range, inclusive." + supplementalGroups: + type: object + description: "Controls the supplementalGroups values that are allowed in a Pod or container-level SecurityContext." + properties: + rule: + type: string + description: "A strategy for applying the supplementalGroups restriction." + enum: + - MustRunAs + - MayRunAs + - RunAsAny + ranges: + type: array + description: "A list of group ID ranges affected by the rule." + items: + type: object + description: "The range of group IDs affected by the rule." + properties: + min: + type: integer + description: "The minimum group ID in the range, inclusive." + max: + type: integer + description: "The maximum group ID in the range, inclusive." + fsGroup: + type: object + description: "Controls the fsGroup values that are allowed in a Pod or container-level SecurityContext." + properties: + rule: + type: string + description: "A strategy for applying the fsGroup restriction." + enum: + - MustRunAs + - MayRunAs + - RunAsAny + ranges: + type: array + description: "A list of group ID ranges affected by the rule." + items: + type: object + description: "The range of group IDs affected by the rule." + properties: + min: + type: integer + description: "The minimum group ID in the range, inclusive." + max: + type: integer + description: "The maximum group ID in the range, inclusive." + targets: + - target: admission.k8s.gatekeeper.sh + code: + - engine: K8sNativeValidation + source: + variables: + - name: containers + expression: 'has(object.spec.containers) ? object.spec.containers : []' + - name: initContainers + expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + - name: ephemeralContainers + expression: 'has(object.spec.ephemeralContainers) ? object.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))) + - name: badContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + !(container.image in variables.exemptImages)) + - name: podRunAsUser + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + : null + - name: missingRequiredRunAsUserContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? + (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + )) + - name: processedRunAsUserContainers + expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) + - name: invalidRunAsUserContainers + expression: | + variables.badContainers.filter(container, + !(container.name in variables.processedRunAsUserContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: podRunAsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + : null + - name: missingRequiredRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsFsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + : null + - name: missingRequiredFsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsSupplementalGroups + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + : null + - name: missingRequiredSupplementalGroupsContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + validations: + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - engine: Rego + source: + rego: | + package k8spspallowedusers + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg}] { + # runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable. + not is_update(input.review) + + fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"] + field := fields[_] + container := input_containers[_] + not is_exempt(container) + msg := get_type_violation(field, container) + } + + get_type_violation(field, container) = msg { + field == "runAsUser" + params := input.parameters[field] + msg := get_user_violation(params, container) + } + + get_type_violation(field, container) = msg { + field != "runAsUser" + params := input.parameters[field] + msg := get_violation(field, params, container) + } + + # RunAsUser (separate due to "MustRunAsNonRoot") + get_user_violation(params, container) = msg { + rule := params.rule + provided_user := get_field_value("runAsUser", container, input.review) + not accept_users(rule, provided_user) + msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params]) + } + + get_user_violation(params, container) = msg { + not get_field_value("runAsUser", container, input.review) + params.rule = "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name]) + } + + get_user_violation(params, container) = msg { + params.rule = "MustRunAsNonRoot" + not get_field_value("runAsUser", container, input.review) + not get_field_value("runAsNonRoot", container, input.review) + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) + } + + accept_users("RunAsAny", _) + + accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 + + accept_users("MustRunAs", provided_user) := res { + ranges := input.parameters.runAsUser.ranges + res := is_in_range(provided_user, ranges) + } + + # Group Options + get_violation(field, params, container) = msg { + rule := params.rule + provided_value := get_field_value(field, container, input.review) + not is_array(provided_value) + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params]) + } + # SupplementalGroups is array value + get_violation(field, params, container) = msg { + rule := params.rule + array_value := get_field_value(field, container, input.review) + is_array(array_value) + provided_value := array_value[_] + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params]) + } + + get_violation(field, params, container) = msg { + not get_field_value(field, container, input.review) + params.rule == "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) + } + + accept_value("RunAsAny", _, _) + + accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + + accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + + + # If container level is provided, that takes precedence + get_field_value(field, container, _) := get_seccontext_field(field, container) + + # If no container level exists, use pod level + get_field_value(field, container, review) = out { + not has_seccontext_field(field, container) + review.kind.kind == "Pod" + pod_value := get_seccontext_field(field, review.object.spec) + out := pod_value + } + + # Helper Functions + is_in_range(val, ranges) = res { + matching := {1 | val >= ranges[j].min; val <= ranges[j].max} + res := count(matching) > 0 + } + + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) + } + + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) == false + } + + get_seccontext_field(field, obj) = out { + out = obj.securityContext[field] + } + + 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[_] + } + 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/users/samples/psp-pods-allowed-user-ranges/constraint.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml index e69974578..37f88d63b 100644 --- a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -9,7 +9,7 @@ spec: kinds: ["Pod"] parameters: runAsUser: - rule: MustRunAs # MustRunAsNonRoot # RunAsAny + rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny ranges: - min: 100 max: 200 diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 613fc9307..ceee1dc79 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspallowedusers annotations: metadata.gatekeeper.sh/title: "Allowed Users" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.1.0 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and @@ -132,158 +132,341 @@ spec: description: "The maximum group ID in the range, inclusive." targets: - target: admission.k8s.gatekeeper.sh - rego: | - package k8spspallowedusers + code: + - engine: K8sNativeValidation + source: + variables: + - name: containers + expression: 'has(object.spec.containers) ? object.spec.containers : []' + - name: initContainers + expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + - name: ephemeralContainers + expression: 'has(object.spec.ephemeralContainers) ? object.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))) + - name: badContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + !(container.image in variables.exemptImages)) + - name: podRunAsUser + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + : null + - name: missingRequiredRunAsUserContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? + (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + )) + - name: processedRunAsUserContainers + expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) + - name: invalidRunAsUserContainers + expression: | + variables.badContainers.filter(container, + !(container.name in variables.processedRunAsUserContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: podRunAsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + : null + - name: missingRequiredRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsFsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + : null + - name: missingRequiredFsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsSupplementalGroups + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + : null + - name: missingRequiredSupplementalGroupsContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + validations: + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - engine: Rego + source: + rego: | + package k8spspallowedusers - import data.lib.exclude_update.is_update - import data.lib.exempt_container.is_exempt + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt - violation[{"msg": msg}] { - # runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable. - not is_update(input.review) + violation[{"msg": msg}] { + # runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable. + not is_update(input.review) - fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"] - field := fields[_] - container := input_containers[_] - not is_exempt(container) - msg := get_type_violation(field, container) - } + fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"] + field := fields[_] + container := input_containers[_] + not is_exempt(container) + msg := get_type_violation(field, container) + } - get_type_violation(field, container) = msg { - field == "runAsUser" - params := input.parameters[field] - msg := get_user_violation(params, container) - } + get_type_violation(field, container) = msg { + field == "runAsUser" + params := input.parameters[field] + msg := get_user_violation(params, container) + } - get_type_violation(field, container) = msg { - field != "runAsUser" - params := input.parameters[field] - msg := get_violation(field, params, container) - } + get_type_violation(field, container) = msg { + field != "runAsUser" + params := input.parameters[field] + msg := get_violation(field, params, container) + } - # RunAsUser (separate due to "MustRunAsNonRoot") - get_user_violation(params, container) = msg { - rule := params.rule - provided_user := get_field_value("runAsUser", container, input.review) - not accept_users(rule, provided_user) - msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params]) - } + # RunAsUser (separate due to "MustRunAsNonRoot") + get_user_violation(params, container) = msg { + rule := params.rule + provided_user := get_field_value("runAsUser", container, input.review) + not accept_users(rule, provided_user) + msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params]) + } - get_user_violation(params, container) = msg { - not get_field_value("runAsUser", container, input.review) - params.rule = "MustRunAs" - msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name]) - } + get_user_violation(params, container) = msg { + not get_field_value("runAsUser", container, input.review) + params.rule = "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name]) + } - get_user_violation(params, container) = msg { - params.rule = "MustRunAsNonRoot" - not get_field_value("runAsUser", container, input.review) - not get_field_value("runAsNonRoot", container, input.review) - msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) - } + get_user_violation(params, container) = msg { + params.rule = "MustRunAsNonRoot" + not get_field_value("runAsUser", container, input.review) + not get_field_value("runAsNonRoot", container, input.review) + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) + } - accept_users("RunAsAny", _) + accept_users("RunAsAny", _) - accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 + accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 - accept_users("MustRunAs", provided_user) := res { - ranges := input.parameters.runAsUser.ranges - res := is_in_range(provided_user, ranges) - } + accept_users("MustRunAs", provided_user) := res { + ranges := input.parameters.runAsUser.ranges + res := is_in_range(provided_user, ranges) + } - # Group Options - get_violation(field, params, container) = msg { - rule := params.rule - provided_value := get_field_value(field, container, input.review) - not is_array(provided_value) - not accept_value(rule, provided_value, params.ranges) - msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params]) - } - # SupplementalGroups is array value - get_violation(field, params, container) = msg { - rule := params.rule - array_value := get_field_value(field, container, input.review) - is_array(array_value) - provided_value := array_value[_] - not accept_value(rule, provided_value, params.ranges) - msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params]) - } + # Group Options + get_violation(field, params, container) = msg { + rule := params.rule + provided_value := get_field_value(field, container, input.review) + not is_array(provided_value) + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params]) + } + # SupplementalGroups is array value + get_violation(field, params, container) = msg { + rule := params.rule + array_value := get_field_value(field, container, input.review) + is_array(array_value) + provided_value := array_value[_] + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params]) + } - get_violation(field, params, container) = msg { - not get_field_value(field, container, input.review) - params.rule == "MustRunAs" - msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) - } + get_violation(field, params, container) = msg { + not get_field_value(field, container, input.review) + params.rule == "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) + } - accept_value("RunAsAny", _, _) + accept_value("RunAsAny", _, _) - accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - # If container level is provided, that takes precedence - get_field_value(field, container, _) := get_seccontext_field(field, container) + # If container level is provided, that takes precedence + get_field_value(field, container, _) := get_seccontext_field(field, container) - # If no container level exists, use pod level - get_field_value(field, container, review) = out { - not has_seccontext_field(field, container) - review.kind.kind == "Pod" - pod_value := get_seccontext_field(field, review.object.spec) - out := pod_value - } + # If no container level exists, use pod level + get_field_value(field, container, review) = out { + not has_seccontext_field(field, container) + review.kind.kind == "Pod" + pod_value := get_seccontext_field(field, review.object.spec) + out := pod_value + } - # Helper Functions - is_in_range(val, ranges) = res { - matching := {1 | val >= ranges[j].min; val <= ranges[j].max} - res := count(matching) > 0 - } + # Helper Functions + is_in_range(val, ranges) = res { + matching := {1 | val >= ranges[j].min; val <= ranges[j].max} + res := count(matching) > 0 + } - has_seccontext_field(field, obj) { - get_seccontext_field(field, obj) - } + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) + } - has_seccontext_field(field, obj) { - get_seccontext_field(field, obj) == false - } + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) == false + } - get_seccontext_field(field, obj) = out { - out = obj.securityContext[field] - } + get_seccontext_field(field, obj) = out { + out = obj.securityContext[field] + } - 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[_] - } - libs: - - | - package lib.exclude_update + 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[_] + } + libs: + - | + package lib.exclude_update - is_update(review) { - review.operation == "UPDATE" - } - - | - package lib.exempt_container + 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) - } + 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) { + not endswith(exemption, "*") + exemption == img + } - _matches_exemption(img, exemption) { - endswith(exemption, "*") - prefix := trim_suffix(exemption, "*") - startswith(img, prefix) - } + _matches_exemption(img, exemption) { + endswith(exemption, "*") + prefix := trim_suffix(exemption, "*") + startswith(img, prefix) + } diff --git a/src/pod-security-policy/users/constraint.tmpl b/src/pod-security-policy/users/constraint.tmpl index 29523b763..79e262927 100644 --- a/src/pod-security-policy/users/constraint.tmpl +++ b/src/pod-security-policy/users/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspallowedusers annotations: metadata.gatekeeper.sh/title: "Allowed Users" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.1.0 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and @@ -132,10 +132,16 @@ spec: description: "The maximum group ID in the range, inclusive." targets: - target: admission.k8s.gatekeeper.sh - rego: | -{{ file.Read "src/pod-security-policy/users/src.rego" | strings.Indent 8 | strings.TrimSuffix "\n" }} - libs: - - | -{{ file.Read "src/pod-security-policy/users/lib_exclude_update.rego" | strings.Indent 10 | strings.TrimSuffix "\n" }} - - | -{{ file.Read "src/pod-security-policy/users/lib_exempt_container.rego" | strings.Indent 10 | strings.TrimSuffix "\n" }} + code: + - engine: K8sNativeValidation + source: +{{ file.Read "src/pod-security-policy/users/src.cel" | strings.Indent 10 | strings.TrimSuffix "\n" }} + - engine: Rego + source: + rego: | +{{ file.Read "src/pod-security-policy/users/src.rego" | strings.Indent 12 | strings.TrimSuffix "\n" }} + libs: + - | +{{ file.Read "src/pod-security-policy/users/lib_exclude_update.rego" | strings.Indent 14 | strings.TrimSuffix "\n" }} + - | +{{ file.Read "src/pod-security-policy/users/lib_exempt_container.rego" | strings.Indent 14 | strings.TrimSuffix "\n" }} diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel new file mode 100644 index 000000000..f0ff3c09f --- /dev/null +++ b/src/pod-security-policy/users/src.cel @@ -0,0 +1,178 @@ +variables: +- name: containers + expression: 'has(object.spec.containers) ? object.spec.containers : []' +- name: initContainers + expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' +- name: ephemeralContainers + expression: 'has(object.spec.ephemeralContainers) ? object.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))) +- name: badContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + !(container.image in variables.exemptImages)) +- name: podRunAsUser + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + : null +- name: missingRequiredRunAsUserContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) +- name: missingRequiredRunAsNonRootContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? + (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + )) +- name: processedRunAsUserContainers + expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) +- name: invalidRunAsUserContainers + expression: | + variables.badContainers.filter(container, + !(container.name in variables.processedRunAsUserContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) +- name: podRunAsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + : null +- name: missingRequiredRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) +- name: invalidRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: podRunAsFsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + : null +- name: missingRequiredFsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) +- name: invalidRunAsFsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: podRunAsSupplementalGroups + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + : null +- name: missingRequiredSupplementalGroupsContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) +- name: invalidSupplimentalGroupsContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) +validations: +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index b9b79acfd..a9cf8fe91 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -16,7 +16,7 @@ metadata: name: k8spspallowedusers annotations: metadata.gatekeeper.sh/title: "Allowed Users" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.1.0 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and @@ -144,161 +144,344 @@ spec: description: "The maximum group ID in the range, inclusive." targets: - target: admission.k8s.gatekeeper.sh - rego: | - package k8spspallowedusers - - import data.lib.exclude_update.is_update - import data.lib.exempt_container.is_exempt - - violation[{"msg": msg}] { - # runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable. - not is_update(input.review) - - fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"] - field := fields[_] - container := input_containers[_] - not is_exempt(container) - msg := get_type_violation(field, container) - } - - get_type_violation(field, container) = msg { - field == "runAsUser" - params := input.parameters[field] - msg := get_user_violation(params, container) - } - - get_type_violation(field, container) = msg { - field != "runAsUser" - params := input.parameters[field] - msg := get_violation(field, params, container) - } - - # RunAsUser (separate due to "MustRunAsNonRoot") - get_user_violation(params, container) = msg { - rule := params.rule - provided_user := get_field_value("runAsUser", container, input.review) - not accept_users(rule, provided_user) - msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params]) - } - - get_user_violation(params, container) = msg { - not get_field_value("runAsUser", container, input.review) - params.rule = "MustRunAs" - msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name]) - } - - get_user_violation(params, container) = msg { - params.rule = "MustRunAsNonRoot" - not get_field_value("runAsUser", container, input.review) - not get_field_value("runAsNonRoot", container, input.review) - msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) - } - - accept_users("RunAsAny", _) - - accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 - - accept_users("MustRunAs", provided_user) := res { - ranges := input.parameters.runAsUser.ranges - res := is_in_range(provided_user, ranges) - } - - # Group Options - get_violation(field, params, container) = msg { - rule := params.rule - provided_value := get_field_value(field, container, input.review) - not is_array(provided_value) - not accept_value(rule, provided_value, params.ranges) - msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params]) - } - # SupplementalGroups is array value - get_violation(field, params, container) = msg { - rule := params.rule - array_value := get_field_value(field, container, input.review) - is_array(array_value) - provided_value := array_value[_] - not accept_value(rule, provided_value, params.ranges) - msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params]) - } - - get_violation(field, params, container) = msg { - not get_field_value(field, container, input.review) - params.rule == "MustRunAs" - msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) - } - - accept_value("RunAsAny", _, _) - - accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - - accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - - - # If container level is provided, that takes precedence - get_field_value(field, container, _) := get_seccontext_field(field, container) - - # If no container level exists, use pod level - get_field_value(field, container, review) = out { - not has_seccontext_field(field, container) - review.kind.kind == "Pod" - pod_value := get_seccontext_field(field, review.object.spec) - out := pod_value - } - - # Helper Functions - is_in_range(val, ranges) = res { - matching := {1 | val >= ranges[j].min; val <= ranges[j].max} - res := count(matching) > 0 - } - - has_seccontext_field(field, obj) { - get_seccontext_field(field, obj) - } - - has_seccontext_field(field, obj) { - get_seccontext_field(field, obj) == false - } - - get_seccontext_field(field, obj) = out { - out = obj.securityContext[field] - } - - 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[_] - } - 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) - } + code: + - engine: K8sNativeValidation + source: + variables: + - name: containers + expression: 'has(object.spec.containers) ? object.spec.containers : []' + - name: initContainers + expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + - name: ephemeralContainers + expression: 'has(object.spec.ephemeralContainers) ? object.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))) + - name: badContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, + !(container.image in variables.exemptImages)) + - name: podRunAsUser + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + : null + - name: missingRequiredRunAsUserContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? + (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + )) + - name: processedRunAsUserContainers + expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) + - name: invalidRunAsUserContainers + expression: | + variables.badContainers.filter(container, + !(container.name in variables.processedRunAsUserContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: podRunAsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + : null + - name: missingRequiredRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsFsGroup + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + : null + - name: missingRequiredFsGroupContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: podRunAsSupplementalGroups + expression: | + object.kind == "Pod" ? + (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + : null + - name: missingRequiredSupplementalGroupsContainers + expression: | + variables.badContainers.filter(container, + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsContainers + expression: | + variables.badContainers.filter(container, + !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + validations: + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - engine: Rego + source: + rego: | + package k8spspallowedusers + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg}] { + # runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable. + not is_update(input.review) + + fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"] + field := fields[_] + container := input_containers[_] + not is_exempt(container) + msg := get_type_violation(field, container) + } + + get_type_violation(field, container) = msg { + field == "runAsUser" + params := input.parameters[field] + msg := get_user_violation(params, container) + } + + get_type_violation(field, container) = msg { + field != "runAsUser" + params := input.parameters[field] + msg := get_violation(field, params, container) + } + + # RunAsUser (separate due to "MustRunAsNonRoot") + get_user_violation(params, container) = msg { + rule := params.rule + provided_user := get_field_value("runAsUser", container, input.review) + not accept_users(rule, provided_user) + msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params]) + } + + get_user_violation(params, container) = msg { + not get_field_value("runAsUser", container, input.review) + params.rule = "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name]) + } + + get_user_violation(params, container) = msg { + params.rule = "MustRunAsNonRoot" + not get_field_value("runAsUser", container, input.review) + not get_field_value("runAsNonRoot", container, input.review) + msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) + } + + accept_users("RunAsAny", _) + + accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 + + accept_users("MustRunAs", provided_user) := res { + ranges := input.parameters.runAsUser.ranges + res := is_in_range(provided_user, ranges) + } + + # Group Options + get_violation(field, params, container) = msg { + rule := params.rule + provided_value := get_field_value(field, container, input.review) + not is_array(provided_value) + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params]) + } + # SupplementalGroups is array value + get_violation(field, params, container) = msg { + rule := params.rule + array_value := get_field_value(field, container, input.review) + is_array(array_value) + provided_value := array_value[_] + not accept_value(rule, provided_value, params.ranges) + msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params]) + } + + get_violation(field, params, container) = msg { + not get_field_value(field, container, input.review) + params.rule == "MustRunAs" + msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) + } + + accept_value("RunAsAny", _, _) + + accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + + accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) + + + # If container level is provided, that takes precedence + get_field_value(field, container, _) := get_seccontext_field(field, container) + + # If no container level exists, use pod level + get_field_value(field, container, review) = out { + not has_seccontext_field(field, container) + review.kind.kind == "Pod" + pod_value := get_seccontext_field(field, review.object.spec) + out := pod_value + } + + # Helper Functions + is_in_range(val, ranges) = res { + matching := {1 | val >= ranges[j].min; val <= ranges[j].max} + res := count(matching) > 0 + } + + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) + } + + has_seccontext_field(field, obj) { + get_seccontext_field(field, obj) == false + } + + get_seccontext_field(field, obj) = out { + out = obj.securityContext[field] + } + + 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[_] + } + 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) + } ``` @@ -325,7 +508,7 @@ spec: kinds: ["Pod"] parameters: runAsUser: - rule: MustRunAs # MustRunAsNonRoot # RunAsAny + rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny ranges: - min: 100 max: 200 From 475b94d9e5c006ce497ce415a05c5ea12e9c647d Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Thu, 30 May 2024 00:35:17 +0000 Subject: [PATCH 02/12] using anyObject Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../users/1.1.0/template.yaml | 24 +++++++++---------- .../pod-security-policy/users/template.yaml | 24 +++++++++---------- src/pod-security-policy/users/src.cel | 24 +++++++++---------- website/docs/validation/users.md | 24 +++++++++---------- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index d4a7dcf71..6f58d7ca9 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: 5d2cc4fd33ea1151f64adb0376d3164e93bea5bdfcc39449a93342d6209d3672 +digest: d6df9c86d8c80e8d4928d0b97ce541e68a4029a7d7c44f6367027d37faae5bf2 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index ceee1dc79..c21b66cba 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -137,11 +137,11 @@ spec: source: variables: - name: containers - expression: 'has(object.spec.containers) ? object.spec.containers : []' + expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' - name: initContainers - expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' - name: ephemeralContainers - expression: 'has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []' + expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' - name: exemptImagePrefixes expression: | !has(variables.params.exemptImages) ? [] : @@ -161,8 +161,8 @@ spec: !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) : null - name: missingRequiredRunAsUserContainers expression: | @@ -174,7 +174,7 @@ spec: expression: | variables.badContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) @@ -203,8 +203,8 @@ spec: ) - name: podRunAsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) : null - name: missingRequiredRunAsGroupContainers expression: | @@ -235,8 +235,8 @@ spec: ) - name: podRunAsFsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) : null - name: missingRequiredFsGroupContainers expression: | @@ -267,8 +267,8 @@ spec: ) - name: podRunAsSupplementalGroups expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) : null - name: missingRequiredSupplementalGroupsContainers expression: | diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index ceee1dc79..c21b66cba 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -137,11 +137,11 @@ spec: source: variables: - name: containers - expression: 'has(object.spec.containers) ? object.spec.containers : []' + expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' - name: initContainers - expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' - name: ephemeralContainers - expression: 'has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []' + expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' - name: exemptImagePrefixes expression: | !has(variables.params.exemptImages) ? [] : @@ -161,8 +161,8 @@ spec: !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) : null - name: missingRequiredRunAsUserContainers expression: | @@ -174,7 +174,7 @@ spec: expression: | variables.badContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) @@ -203,8 +203,8 @@ spec: ) - name: podRunAsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) : null - name: missingRequiredRunAsGroupContainers expression: | @@ -235,8 +235,8 @@ spec: ) - name: podRunAsFsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) : null - name: missingRequiredFsGroupContainers expression: | @@ -267,8 +267,8 @@ spec: ) - name: podRunAsSupplementalGroups expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) : null - name: missingRequiredSupplementalGroupsContainers expression: | diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index f0ff3c09f..1528b5aea 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -1,10 +1,10 @@ variables: - name: containers - expression: 'has(object.spec.containers) ? object.spec.containers : []' + expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' - name: initContainers - expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' - name: ephemeralContainers - expression: 'has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []' + expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' - name: exemptImagePrefixes expression: | !has(variables.params.exemptImages) ? [] : @@ -24,8 +24,8 @@ variables: !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) : null - name: missingRequiredRunAsUserContainers expression: | @@ -37,7 +37,7 @@ variables: expression: | variables.badContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) @@ -66,8 +66,8 @@ variables: ) - name: podRunAsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) : null - name: missingRequiredRunAsGroupContainers expression: | @@ -98,8 +98,8 @@ variables: ) - name: podRunAsFsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) : null - name: missingRequiredFsGroupContainers expression: | @@ -130,8 +130,8 @@ variables: ) - name: podRunAsSupplementalGroups expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) : null - name: missingRequiredSupplementalGroupsContainers expression: | diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index a9cf8fe91..d6d91d0e7 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -149,11 +149,11 @@ spec: source: variables: - name: containers - expression: 'has(object.spec.containers) ? object.spec.containers : []' + expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' - name: initContainers - expression: 'has(object.spec.initContainers) ? object.spec.initContainers : []' + expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' - name: ephemeralContainers - expression: 'has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []' + expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' - name: exemptImagePrefixes expression: | !has(variables.params.exemptImages) ? [] : @@ -173,8 +173,8 @@ spec: !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsUser) ? object.spec.securityContext.runAsUser : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) : null - name: missingRequiredRunAsUserContainers expression: | @@ -186,7 +186,7 @@ spec: expression: | variables.badContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(object.spec.securityContext) && !(has(object.spec.securityContext.runAsUser) || has(object.spec.securityContext.runAsNonRoot))) : false + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) @@ -215,8 +215,8 @@ spec: ) - name: podRunAsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.runAsGroup) ? object.spec.securityContext.runAsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) : null - name: missingRequiredRunAsGroupContainers expression: | @@ -247,8 +247,8 @@ spec: ) - name: podRunAsFsGroup expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.fsGroup) ? object.spec.securityContext.fsGroup : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) : null - name: missingRequiredFsGroupContainers expression: | @@ -279,8 +279,8 @@ spec: ) - name: podRunAsSupplementalGroups expression: | - object.kind == "Pod" ? - (has(object.spec.securityContext) && has(object.spec.securityContext.supplementalGroups) ? object.spec.securityContext.supplementalGroups : null) + variables.anyObject.kind == "Pod" ? + (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) : null - name: missingRequiredSupplementalGroupsContainers expression: | From 6730ee5f0389526057f2e16852d592c89e4e2265 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Thu, 30 May 2024 01:22:04 +0000 Subject: [PATCH 03/12] fixing ci errors Signed-off-by: Jaydip Gabani --- .../pod-security-policy/users/1.1.0/artifacthub-pkg.yml | 2 +- .../library/pod-security-policy/users/1.1.0/template.yaml | 4 ++-- library/pod-security-policy/users/template.yaml | 4 ++-- src/pod-security-policy/users/constraint.tmpl | 4 ++-- website/docs/validation/users.md | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 6f58d7ca9..45d1b7769 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: d6df9c86d8c80e8d4928d0b97ce541e68a4029a7d7c44f6367027d37faae5bf2 +digest: d81aa3b4740dbcb1fcf63001f224967ea78d4597a297ff7c2e8ac8af6c909674 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index c21b66cba..1fb773c7e 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -444,13 +444,13 @@ spec: c := input.review.object.spec.ephemeralContainers[_] } libs: - - | + - | package lib.exclude_update is_update(review) { review.operation == "UPDATE" } - - | + - | package lib.exempt_container is_exempt(container) { diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index c21b66cba..1fb773c7e 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -444,13 +444,13 @@ spec: c := input.review.object.spec.ephemeralContainers[_] } libs: - - | + - | package lib.exclude_update is_update(review) { review.operation == "UPDATE" } - - | + - | package lib.exempt_container is_exempt(container) { diff --git a/src/pod-security-policy/users/constraint.tmpl b/src/pod-security-policy/users/constraint.tmpl index 79e262927..6b53dcd3b 100644 --- a/src/pod-security-policy/users/constraint.tmpl +++ b/src/pod-security-policy/users/constraint.tmpl @@ -141,7 +141,7 @@ spec: rego: | {{ file.Read "src/pod-security-policy/users/src.rego" | strings.Indent 12 | strings.TrimSuffix "\n" }} libs: - - | + - | {{ file.Read "src/pod-security-policy/users/lib_exclude_update.rego" | strings.Indent 14 | strings.TrimSuffix "\n" }} - - | + - | {{ file.Read "src/pod-security-policy/users/lib_exempt_container.rego" | strings.Indent 14 | strings.TrimSuffix "\n" }} diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index d6d91d0e7..1bf2ba99d 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -456,13 +456,13 @@ spec: c := input.review.object.spec.ephemeralContainers[_] } libs: - - | + - | package lib.exclude_update is_update(review) { review.operation == "UPDATE" } - - | + - | package lib.exempt_container is_exempt(container) { From 2e6de13b5dbad734560a091a526b515d9129cffc Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Fri, 12 Jul 2024 21:41:46 +0000 Subject: [PATCH 04/12] fixing exists vs all Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../constraint.yaml | 2 +- .../users/1.1.0/template.yaml | 40 +++++++++--------- .../constraint.yaml | 2 +- .../pod-security-policy/users/template.yaml | 40 +++++++++--------- src/pod-security-policy/users/src.cel | 40 +++++++++--------- website/docs/validation/users.md | 42 +++++++++---------- 7 files changed, 84 insertions(+), 84 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 45d1b7769..b6d4ffb17 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: d81aa3b4740dbcb1fcf63001f224967ea78d4597a297ff7c2e8ac8af6c909674 +digest: afe1b66026bf6fbbbb9433198e5f71cbcf5c86c8f115f566077aeaec4fb65ba5 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml index 37f88d63b..e69974578 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -9,7 +9,7 @@ spec: kinds: ["Pod"] parameters: runAsUser: - rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny + rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: - min: 100 max: 200 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 1fb773c7e..b70432fc2 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -155,7 +155,7 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: badContainers + - name: candidateContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) @@ -166,21 +166,21 @@ spec: : null - name: missingRequiredRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - name: missingRequiredRunAsNonRootContainers expression: | - variables.badContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false + variables.candidateContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -194,8 +194,8 @@ spec: ( variables.params.runAsUser.rule == "MustRunAs" ? ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) ) : false ) ) @@ -208,14 +208,14 @@ spec: : null - name: missingRequiredRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -225,8 +225,8 @@ spec: (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) ) ) ) @@ -240,14 +240,14 @@ spec: : null - name: missingRequiredFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -257,8 +257,8 @@ spec: (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) ) ) ) @@ -272,13 +272,13 @@ spec: : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -288,8 +288,8 @@ spec: (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) ) ) ) diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml index 37f88d63b..e69974578 100644 --- a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -9,7 +9,7 @@ spec: kinds: ["Pod"] parameters: runAsUser: - rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny + rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: - min: 100 max: 200 diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 1fb773c7e..b70432fc2 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -155,7 +155,7 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: badContainers + - name: candidateContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) @@ -166,21 +166,21 @@ spec: : null - name: missingRequiredRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - name: missingRequiredRunAsNonRootContainers expression: | - variables.badContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false + variables.candidateContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -194,8 +194,8 @@ spec: ( variables.params.runAsUser.rule == "MustRunAs" ? ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) ) : false ) ) @@ -208,14 +208,14 @@ spec: : null - name: missingRequiredRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -225,8 +225,8 @@ spec: (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) ) ) ) @@ -240,14 +240,14 @@ spec: : null - name: missingRequiredFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -257,8 +257,8 @@ spec: (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) ) ) ) @@ -272,13 +272,13 @@ spec: : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -288,8 +288,8 @@ spec: (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) ) ) ) diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 1528b5aea..6a32133d1 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -18,7 +18,7 @@ variables: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) -- name: badContainers +- name: candidateContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) @@ -29,21 +29,21 @@ variables: : null - name: missingRequiredRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - name: missingRequiredRunAsNonRootContainers expression: | - variables.badContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false + variables.candidateContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -57,8 +57,8 @@ variables: ( variables.params.runAsUser.rule == "MustRunAs" ? ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) ) : false ) ) @@ -71,14 +71,14 @@ variables: : null - name: missingRequiredRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -88,8 +88,8 @@ variables: (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) ) ) ) @@ -103,14 +103,14 @@ variables: : null - name: missingRequiredFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -120,8 +120,8 @@ variables: (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) ) ) ) @@ -135,13 +135,13 @@ variables: : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -151,8 +151,8 @@ variables: (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) ) ) ) diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 1bf2ba99d..f445603d3 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -167,7 +167,7 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: badContainers + - name: candidateContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) @@ -178,21 +178,21 @@ spec: : null - name: missingRequiredRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - name: missingRequiredRunAsNonRootContainers expression: | - variables.badContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) || has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) || has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false + variables.candidateContainers.filter(container, + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? + (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false )) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -206,8 +206,8 @@ spec: ( variables.params.runAsUser.rule == "MustRunAs" ? ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.all(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.all(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) ) : false ) ) @@ -220,14 +220,14 @@ spec: : null - name: missingRequiredRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -237,8 +237,8 @@ spec: (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.all(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.all(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) ) ) ) @@ -252,14 +252,14 @@ spec: : null - name: missingRequiredFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -269,8 +269,8 @@ spec: (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.all(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.all(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) ) ) ) @@ -284,13 +284,13 @@ spec: : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.badContainers.filter(container, + variables.candidateContainers.filter(container, !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -300,8 +300,8 @@ spec: (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && ( has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.all(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.all(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) ) ) ) @@ -508,7 +508,7 @@ spec: kinds: ["Pod"] parameters: runAsUser: - rule: MustRunAsNonRoot # MustRunAsNonRoot # RunAsAny + rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: - min: 100 max: 200 From 34467803a4b27c0e13ea1e7f7001b9e2dde3b3d7 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Mon, 15 Jul 2024 18:29:02 +0000 Subject: [PATCH 05/12] fixing missingRequiredRunAsNonRoot Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../pod-security-policy/users/1.1.0/template.yaml | 13 ++++++++++--- library/pod-security-policy/users/template.yaml | 13 ++++++++++--- src/pod-security-policy/users/src.cel | 13 ++++++++++--- website/docs/validation/users.md | 13 ++++++++++--- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index b6d4ffb17..1ea2c1f20 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: afe1b66026bf6fbbbb9433198e5f71cbcf5c86c8f115f566077aeaec4fb65ba5 +digest: 1a2443f09b2e751b9055bfb94f8874274b79a12d1947476348de5103e7c25324 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index b70432fc2..87b50c1c0 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -170,12 +170,19 @@ spec: has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | variables.candidateContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false - )) + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index b70432fc2..87b50c1c0 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -170,12 +170,19 @@ spec: has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | variables.candidateContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false - )) + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 6a32133d1..7d54fcf50 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -33,12 +33,19 @@ variables: has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) +- name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | variables.candidateContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false - )) + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index f445603d3..78c532322 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -182,12 +182,19 @@ spec: has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | variables.candidateContainers.filter(container, - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") && ((has(container.securityContext) && !(has(container.securityContext.runAsUser) && has(container.securityContext.runAsNonRoot))) ? - (has(variables.anyObject.spec.securityContext) && !(has(variables.anyObject.spec.securityContext.runAsUser) && has(variables.anyObject.spec.securityContext.runAsNonRoot))) : false - )) + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers From dbba915f252cefd60dabf3de11d6c74ffe296fe8 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Wed, 7 Aug 2024 17:50:25 +0000 Subject: [PATCH 06/12] processing each container types separately Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../example_disallowed.yaml | 6 + .../users/1.1.0/template.yaml | 360 +++++++++++++++-- .../example_disallowed.yaml | 6 + .../pod-security-policy/users/template.yaml | 360 +++++++++++++++-- src/pod-security-policy/users/src.cel | 360 +++++++++++++++-- website/docs/validation/users.md | 366 ++++++++++++++++-- 7 files changed, 1311 insertions(+), 149 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 1ea2c1f20..a341be89b 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: 1a2443f09b2e751b9055bfb94f8874274b79a12d1947476348de5103e7c25324 +digest: b70711f62a3207d1cb7c374416567bc9d9fee374bbc1fa356bbd13ab9a192daf license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml index 516cce14b..01af42e18 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml @@ -15,3 +15,9 @@ spec: securityContext: runAsUser: 250 runAsGroup: 250 + initContainers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 87b50c1c0..618d304d6 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -155,39 +155,45 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: candidateContainers - expression: | - (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, - !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) - : null + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + - name: podRunAsSupplementalGroups + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + - name: podRunAsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + - name: podRunAsFsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - - name: missingRunAsNonRootGlobal - expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal + (!has(container.securityContext) || ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) + )) || variables.missingRunAsNonRootGlobal ) : false ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -208,21 +214,18 @@ spec: ) ) : false ) - - name: podRunAsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) - : null - name: missingRequiredRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -240,21 +243,17 @@ spec: : false ) ) - - name: podRunAsFsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) - : null - name: missingRequiredFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -272,20 +271,17 @@ spec: : false ) ) - - name: podRunAsSupplementalGroups - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) - : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -303,6 +299,264 @@ spec: : false ) ) + - name: missingRequiredRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserInitContainers + expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) + - name: invalidRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserInitContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + - name: missingRequiredRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserEphemeralContainers + expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) + - name: invalidRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserEphemeralContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' @@ -320,6 +574,38 @@ spec: messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' - engine: Rego source: rego: | diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml index 516cce14b..01af42e18 100644 --- a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml @@ -15,3 +15,9 @@ spec: securityContext: runAsUser: 250 runAsGroup: 250 + initContainers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 87b50c1c0..618d304d6 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -155,39 +155,45 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: candidateContainers - expression: | - (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, - !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) - : null + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + - name: podRunAsSupplementalGroups + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + - name: podRunAsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + - name: podRunAsFsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - - name: missingRunAsNonRootGlobal - expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal + (!has(container.securityContext) || ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) + )) || variables.missingRunAsNonRootGlobal ) : false ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -208,21 +214,18 @@ spec: ) ) : false ) - - name: podRunAsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) - : null - name: missingRequiredRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -240,21 +243,17 @@ spec: : false ) ) - - name: podRunAsFsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) - : null - name: missingRequiredFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -272,20 +271,17 @@ spec: : false ) ) - - name: podRunAsSupplementalGroups - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) - : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -303,6 +299,264 @@ spec: : false ) ) + - name: missingRequiredRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserInitContainers + expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) + - name: invalidRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserInitContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + - name: missingRequiredRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserEphemeralContainers + expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) + - name: invalidRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserEphemeralContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' @@ -320,6 +574,38 @@ spec: messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' - engine: Rego source: rego: | diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 7d54fcf50..7db5dbcdf 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -18,39 +18,45 @@ variables: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) -- name: candidateContainers - expression: | - (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, - !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) - : null + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null +- name: podRunAsSupplementalGroups + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null +- name: podRunAsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null +- name: podRunAsFsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null +- name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) -- name: missingRunAsNonRootGlobal - expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal + (!has(container.securityContext) || ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) + )) || variables.missingRunAsNonRootGlobal ) : false ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -71,21 +77,18 @@ variables: ) ) : false ) -- name: podRunAsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) - : null - name: missingRequiredRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -103,21 +106,17 @@ variables: : false ) ) -- name: podRunAsFsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) - : null - name: missingRequiredFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -135,20 +134,17 @@ variables: : false ) ) -- name: podRunAsSupplementalGroups - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) - : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -166,6 +162,264 @@ variables: : false ) ) +- name: missingRequiredRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) +- name: missingRequiredRunAsNonRootInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) +- name: processedRunAsUserInitContainers + expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) +- name: invalidRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserInitContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) +- name: missingRequiredRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) +- name: invalidRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: missingRequiredFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) +- name: invalidRunAsFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: missingRequiredSupplementalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) +- name: invalidSupplimentalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) +- name: missingRequiredRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) +- name: missingRequiredRunAsNonRootEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) +- name: processedRunAsUserEphemeralContainers + expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) +- name: invalidRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserEphemeralContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) +- name: missingRequiredRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) +- name: invalidRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: missingRequiredFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) +- name: invalidRunAsFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) +- name: missingRequiredSupplementalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) +- name: invalidSupplimentalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' @@ -183,3 +437,35 @@ validations: messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 78c532322..98c49c0c5 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -167,39 +167,45 @@ spec: (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, container.image in variables.exemptImageExplicit || variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - - name: candidateContainers - expression: | - (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, - !(container.image in variables.exemptImages)) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null) - : null + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + - name: podRunAsSupplementalGroups + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + - name: podRunAsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + - name: podRunAsFsGroup + expression: | + variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: missingRunAsNonRootGlobal + expression: | + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsUser)) || (variables.podRunAsUser != null))) - - name: missingRunAsNonRootGlobal - expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - name: missingRequiredRunAsNonRootContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal + (!has(container.securityContext) || ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) + )) || variables.missingRunAsNonRootGlobal ) : false ) - name: processedRunAsUserContainers expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - name: invalidRunAsUserContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(container.name in variables.processedRunAsUserContainers) && has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? ( @@ -220,21 +226,18 @@ spec: ) ) : false ) - - name: podRunAsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null) - : null - name: missingRequiredRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || (variables.podRunAsGroup != null)) ) - name: invalidRunAsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? @@ -252,21 +255,17 @@ spec: : false ) ) - - name: podRunAsFsGroup - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null) - : null - name: missingRequiredFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.fsGroup)) || (variables.podRunAsFsGroup != null)) ) - name: invalidRunAsFsGroupContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && ( has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? @@ -284,20 +283,17 @@ spec: : false ) ) - - name: podRunAsSupplementalGroups - expression: | - variables.anyObject.kind == "Pod" ? - (has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null) - : null - name: missingRequiredSupplementalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - name: invalidSupplimentalGroupsContainers expression: | - variables.candidateContainers.filter(container, + variables.containers.filter(container, + !(container.image in variables.exemptImages) && !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && ( has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? @@ -315,6 +311,264 @@ spec: : false ) ) + - name: missingRequiredRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserInitContainers + expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) + - name: invalidRunAsUserInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserInitContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsInitContainers + expression: | + variables.initContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) + - name: missingRequiredRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsUser)) || + (variables.podRunAsUser != null))) + - name: missingRequiredRunAsNonRootEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? + ( + has(container.securityContext) ? ( + (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal + ) : variables.missingRunAsNonRootGlobal + ) : false + ) + - name: processedRunAsUserEphemeralContainers + expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) + - name: invalidRunAsUserEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(container.name in variables.processedRunAsUserEphemeralContainers) && + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? + ( + variables.params.runAsUser.rule == "RunAsAny" ? false : + ( + variables.params.runAsUser.rule == "MustRunAsNonRoot" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : + (variables.podRunAsUser == null) || variables.podRunAsUser == 0 + ) : + ( + variables.params.runAsUser.rule == "MustRunAs" ? + ( + has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) : false + ) + ) + ) : false + ) + - name: missingRequiredRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || + (variables.podRunAsGroup != null)) + ) + - name: invalidRunAsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? + ( + variables.params.runAsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.runAsGroup) ? + !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.fsGroup)) || + (variables.podRunAsFsGroup != null)) + ) + - name: invalidRunAsFsGroupEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? + ( + variables.params.fsGroup.rule == "RunAsAny" ? false : + ( + (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.fsGroup) ? + !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) + ) + ) + ) + : false + ) + ) + - name: missingRequiredSupplementalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && + !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || + (variables.podRunAsSupplementalGroups != null))) + - name: invalidSupplimentalGroupsEphemeralContainers + expression: | + variables.ephemeralContainers.filter(container, + !(container.image in variables.exemptImages) && + !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && + ( + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? + ( + variables.params.supplementalGroups.rule == "RunAsAny" ? false : + ( + (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && + ( + has(container.securityContext) && has(container.securityContext.supplementalGroups) ? + !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : + variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ) + ) + ) + : false + ) + ) validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' @@ -332,6 +586,38 @@ spec: messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' - engine: Rego source: rego: | @@ -566,6 +852,12 @@ spec: securityContext: runAsUser: 250 runAsGroup: 250 + initContainers: + - name: nginx + image: nginx + securityContext: + runAsUser: 250 + runAsGroup: 250 ``` From 8366a0641b1101d7175b197e0052063efa84b957 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Thu, 29 Aug 2024 00:56:58 +0000 Subject: [PATCH 07/12] fixing ci Signed-off-by: Jaydip Gabani --- .../psp-pods-allowed-user-ranges/example_disallowed.yaml | 2 +- .../psp-pods-allowed-user-ranges/example_disallowed.yaml | 2 +- website/docs/validation/users.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml index 01af42e18..4f765794b 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml @@ -16,7 +16,7 @@ spec: runAsUser: 250 runAsGroup: 250 initContainers: - - name: nginx + - name: init-nginx image: nginx securityContext: runAsUser: 250 diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml index 01af42e18..4f765794b 100644 --- a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml @@ -16,7 +16,7 @@ spec: runAsUser: 250 runAsGroup: 250 initContainers: - - name: nginx + - name: init-nginx image: nginx securityContext: runAsUser: 250 diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 98c49c0c5..fb9c63dc9 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -853,7 +853,7 @@ spec: runAsUser: 250 runAsGroup: 250 initContainers: - - name: nginx + - name: init-nginx image: nginx securityContext: runAsUser: 250 From ff6ad88d2bbad789617bf1845a540851606fe880 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Tue, 3 Sep 2024 21:40:49 +0000 Subject: [PATCH 08/12] fixing error msgs Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../users/1.1.0/template.yaml | 48 +++++++++++-------- .../pod-security-policy/users/template.yaml | 48 +++++++++++-------- src/pod-security-policy/users/src.cel | 48 +++++++++++-------- website/docs/validation/users.md | 48 +++++++++++-------- 5 files changed, 109 insertions(+), 85 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index a341be89b..a72123d94 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: b70711f62a3207d1cb7c374416567bc9d9fee374bbc1fa356bbd13ab9a192daf +digest: 8ec0383edcc95ade56ab32b52ce565ea315fc30ca18b337592ed4284c36eeef7 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 618d304d6..6a1b9e597 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -278,7 +278,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsContainers + - name: invalidSupplementalGroupsContainers expression: | variables.containers.filter(container, !(container.image in variables.exemptImages) && @@ -407,7 +407,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsInitContainers + - name: invalidSupplementalGroupsInitContainers expression: | variables.initContainers.filter(container, !(container.image in variables.exemptImages) && @@ -536,7 +536,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsEphemeralContainers + - name: invalidSupplementalGroupsEphemeralContainers expression: | variables.ephemeralContainers.filter(container, !(container.image in variables.exemptImages) && @@ -563,49 +563,55 @@ spec: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - engine: Rego source: rego: | diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 618d304d6..6a1b9e597 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -278,7 +278,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsContainers + - name: invalidSupplementalGroupsContainers expression: | variables.containers.filter(container, !(container.image in variables.exemptImages) && @@ -407,7 +407,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsInitContainers + - name: invalidSupplementalGroupsInitContainers expression: | variables.initContainers.filter(container, !(container.image in variables.exemptImages) && @@ -536,7 +536,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsEphemeralContainers + - name: invalidSupplementalGroupsEphemeralContainers expression: | variables.ephemeralContainers.filter(container, !(container.image in variables.exemptImages) && @@ -563,49 +563,55 @@ spec: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - engine: Rego source: rego: | diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 7db5dbcdf..3f6b73e57 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -141,7 +141,7 @@ variables: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplimentalGroupsContainers +- name: invalidSupplementalGroupsContainers expression: | variables.containers.filter(container, !(container.image in variables.exemptImages) && @@ -270,7 +270,7 @@ variables: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplimentalGroupsInitContainers +- name: invalidSupplementalGroupsInitContainers expression: | variables.initContainers.filter(container, !(container.image in variables.exemptImages) && @@ -399,7 +399,7 @@ variables: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplimentalGroupsEphemeralContainers +- name: invalidSupplementalGroupsEphemeralContainers expression: | variables.ephemeralContainers.filter(container, !(container.image in variables.exemptImages) && @@ -426,46 +426,52 @@ validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' \ No newline at end of file diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index fb9c63dc9..dee3a5a62 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -290,7 +290,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsContainers + - name: invalidSupplementalGroupsContainers expression: | variables.containers.filter(container, !(container.image in variables.exemptImages) && @@ -419,7 +419,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsInitContainers + - name: invalidSupplementalGroupsInitContainers expression: | variables.initContainers.filter(container, !(container.image in variables.exemptImages) && @@ -548,7 +548,7 @@ spec: has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplimentalGroupsEphemeralContainers + - name: invalidSupplementalGroupsEphemeralContainers expression: | variables.ephemeralContainers.filter(container, !(container.image in variables.exemptImages) && @@ -575,49 +575,55 @@ spec: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: " + variables.params.runAsUser.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: " + variables.params.runAsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: " + variables.params.fsGroup.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: " + variables.params.supplementalGroups.ranges.map(range, range.min + "-" + range.max).join(", ")' + messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' + messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - engine: Rego source: rego: | From 093d80abd8961f4796e52867c1b5e16c558e6134 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Thu, 19 Sep 2024 20:06:18 +0000 Subject: [PATCH 09/12] simplifying CEL code Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../users/1.1.0/template.yaml | 456 +----------------- .../pod-security-policy/users/template.yaml | 456 +----------------- src/pod-security-policy/users/src.cel | 456 +----------------- website/docs/validation/users.md | 456 +----------------- 5 files changed, 77 insertions(+), 1749 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index a72123d94..354e2921f 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: 8ec0383edcc95ade56ab32b52ce565ea315fc30ca18b337592ed4284c36eeef7 +digest: 89647a76a0f751668fd9ef9630c8a2ddf6fda516eadd14067a3fd98988e13210 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 6a1b9e597..85d556481 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -158,460 +158,42 @@ spec: - name: podRunAsUser expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - - name: podRunAsSupplementalGroups + - name: podSupplementalGroups expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - - name: podRunAsFsGroup + - name: podFsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: nonExemptContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - - name: missingRequiredRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - (!has(container.securityContext) || ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) - )) || variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserContainers - expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - - name: invalidRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupContainers - expression: | - variables.containers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserInitContainers - expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) - - name: invalidRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserInitContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserEphemeralContainers - expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) - - name: invalidRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserEphemeralContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupEphemeralContainers + - name: violatingMustOrMayRunAsUser expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupEphemeralContainers + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + - name: violatingMustOrMayRunAsGroup expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupEphemeralContainers + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsFsGroup expression: | - variables.ephemeralContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupEphemeralContainers + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsSupplementalGroups expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsEphemeralContainers + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + - name: violatingMustRunAsNonRoot expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsEphemeralContainers + variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + - name: violations expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) + variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups validations: - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' + messageExpression: 'variables.violations.join(", ")' - engine: Rego source: rego: | diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 6a1b9e597..85d556481 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -158,460 +158,42 @@ spec: - name: podRunAsUser expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - - name: podRunAsSupplementalGroups + - name: podSupplementalGroups expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - - name: podRunAsFsGroup + - name: podFsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: nonExemptContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - - name: missingRequiredRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - (!has(container.securityContext) || ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) - )) || variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserContainers - expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - - name: invalidRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupContainers - expression: | - variables.containers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserInitContainers - expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) - - name: invalidRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserInitContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserEphemeralContainers - expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) - - name: invalidRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserEphemeralContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupEphemeralContainers + - name: violatingMustOrMayRunAsUser expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupEphemeralContainers + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + - name: violatingMustOrMayRunAsGroup expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupEphemeralContainers + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsFsGroup expression: | - variables.ephemeralContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupEphemeralContainers + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsSupplementalGroups expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsEphemeralContainers + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + - name: violatingMustRunAsNonRoot expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsEphemeralContainers + variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + - name: violations expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) + variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups validations: - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' + messageExpression: 'variables.violations.join(", ")' - engine: Rego source: rego: | diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 3f6b73e57..99a5adcf2 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -21,457 +21,39 @@ variables: - name: podRunAsUser expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null -- name: podRunAsSupplementalGroups +- name: podSupplementalGroups expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null -- name: podRunAsFsGroup +- name: podFsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null +- name: nonExemptContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) -- name: missingRequiredRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) -- name: missingRequiredRunAsNonRootContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - (!has(container.securityContext) || ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) - )) || variables.missingRunAsNonRootGlobal - ) : false - ) -- name: processedRunAsUserContainers - expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) -- name: invalidRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) -- name: missingRequiredRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) -- name: invalidRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredFsGroupContainers - expression: | - variables.containers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) -- name: invalidRunAsFsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) -- name: missingRequiredRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) -- name: missingRequiredRunAsNonRootInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) -- name: processedRunAsUserInitContainers - expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) -- name: invalidRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserInitContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) -- name: missingRequiredRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) -- name: invalidRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) -- name: invalidRunAsFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) -- name: missingRequiredRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) -- name: missingRequiredRunAsNonRootEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) -- name: processedRunAsUserEphemeralContainers - expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) -- name: invalidRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserEphemeralContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) -- name: missingRequiredRunAsGroupEphemeralContainers +- name: violatingMustOrMayRunAsUser expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) -- name: invalidRunAsGroupEphemeralContainers + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] +- name: violatingMustOrMayRunAsGroup expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredFsGroupEphemeralContainers + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] +- name: violatingMustOrMayRunAsFsGroup expression: | - variables.ephemeralContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) -- name: invalidRunAsFsGroupEphemeralContainers + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] +- name: violatingMustOrMayRunAsSupplementalGroups expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) -- name: missingRequiredSupplementalGroupsEphemeralContainers + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] +- name: violatingMustRunAsNonRoot expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) -- name: invalidSupplementalGroupsEphemeralContainers + variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") +- name: violations expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) + variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups validations: -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' -- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' \ No newline at end of file +- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' + messageExpression: 'variables.violations.join(", ")' \ No newline at end of file diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index dee3a5a62..da252dd66 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -170,460 +170,42 @@ spec: - name: podRunAsUser expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - - name: podRunAsSupplementalGroups + - name: podSupplementalGroups expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - - name: podRunAsFsGroup + - name: podFsGroup expression: | variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + - name: nonExemptContainers + expression: | + (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) - - name: missingRequiredRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - (!has(container.securityContext) || ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) - )) || variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserContainers - expression: (variables.missingRequiredRunAsNonRootContainers + variables.missingRequiredRunAsUserContainers).map(container, container.name) - - name: invalidRunAsUserContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupContainers - expression: | - variables.containers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsContainers - expression: | - variables.containers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserInitContainers - expression: (variables.missingRequiredRunAsNonRootInitContainers + variables.missingRequiredRunAsUserInitContainers).map(container, container.name) - - name: invalidRunAsUserInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserInitContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsInitContainers - expression: | - variables.initContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsInitContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) - - name: missingRequiredRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsUser)) || - (variables.podRunAsUser != null))) - - name: missingRequiredRunAsNonRootEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && (variables.params.runAsUser.rule == "MustRunAsNonRoot") ? - ( - has(container.securityContext) ? ( - (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0) && variables.missingRunAsNonRootGlobal - ) : variables.missingRunAsNonRootGlobal - ) : false - ) - - name: processedRunAsUserEphemeralContainers - expression: (variables.missingRequiredRunAsNonRootEphemeralContainers + variables.missingRequiredRunAsUserEphemeralContainers).map(container, container.name) - - name: invalidRunAsUserEphemeralContainers - expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(container.name in variables.processedRunAsUserEphemeralContainers) && - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) ? - ( - variables.params.runAsUser.rule == "RunAsAny" ? false : - ( - variables.params.runAsUser.rule == "MustRunAsNonRoot" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? (container.securityContext.runAsUser == 0) : - (variables.podRunAsUser == null) || variables.podRunAsUser == 0 - ) : - ( - variables.params.runAsUser.rule == "MustRunAs" ? - ( - has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : - variables.podRunAsUser == null || !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) - ) : false - ) - ) - ) : false - ) - - name: missingRequiredRunAsGroupEphemeralContainers + - name: violatingMustOrMayRunAsUser expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.runAsGroup)) || - (variables.podRunAsGroup != null)) - ) - - name: invalidRunAsGroupEphemeralContainers + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + - name: violatingMustOrMayRunAsGroup expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredRunAsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) ? - ( - variables.params.runAsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.runAsGroup) ? - !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : - variables.podRunAsGroup == null || !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredFsGroupEphemeralContainers + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsFsGroup expression: | - variables.ephemeralContainers.filter(container, - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.fsGroup)) || - (variables.podRunAsFsGroup != null)) - ) - - name: invalidRunAsFsGroupEphemeralContainers + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + - name: violatingMustOrMayRunAsSupplementalGroups expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredFsGroupEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) ? - ( - variables.params.fsGroup.rule == "RunAsAny" ? false : - ( - (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.fsGroup) ? - !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : - variables.podRunAsFsGroup == null || !variables.params.fsGroup.ranges.exists(range, variables.podRunAsFsGroup >= range.min && variables.podRunAsFsGroup <= range.max) - ) - ) - ) - : false - ) - ) - - name: missingRequiredSupplementalGroupsEphemeralContainers + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + - name: violatingMustRunAsNonRoot expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs") && - !((has(container.securityContext) && has(container.securityContext.supplementalGroups)) || - (variables.podRunAsSupplementalGroups != null))) - - name: invalidSupplementalGroupsEphemeralContainers + variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + - name: violations expression: | - variables.ephemeralContainers.filter(container, - !(container.image in variables.exemptImages) && - !(variables.missingRequiredSupplementalGroupsEphemeralContainers.exists(c, c.name == container.name)) && - ( - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) ? - ( - variables.params.supplementalGroups.rule == "RunAsAny" ? false : - ( - (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") && - ( - has(container.securityContext) && has(container.securityContext.supplementalGroups) ? - !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp>= range.min && gp <= range.max)) : - variables.podRunAsSupplementalGroups == null || !variables.params.supplementalGroups.ranges.exists(range, variables.podRunAsSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) - ) - ) - ) - : false - ) - ) + variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups validations: - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupInitContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsInitContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsInitContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsUser"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsNonRootEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsNonRootEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsUserEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsUserEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidRunAsFsGroupEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidRunAsFsGroupEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingRequiredSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.missingRequiredSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' - - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.invalidSupplementalGroupsEphemeralContainers) == 0' - messageExpression: '"Containers " + variables.invalidSupplementalGroupsEphemeralContainers.map(c, c.name).join(", ") + " are attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}"' + - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' + messageExpression: 'variables.violations.join(", ")' - engine: Rego source: rego: | From 7d0f8dcedcb370ba0105b68333c5c4a4944759e0 Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Tue, 1 Oct 2024 17:29:35 +0000 Subject: [PATCH 10/12] formatting CEL code for better readability Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../users/1.1.0/template.yaml | 103 ++++++++++++++++-- .../pod-security-policy/users/template.yaml | 103 ++++++++++++++++-- src/pod-security-policy/users/src.cel | 102 +++++++++++++++-- src/pod-security-policy/users/src.rego | 1 - website/docs/validation/users.md | 103 ++++++++++++++++-- 6 files changed, 365 insertions(+), 49 deletions(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 354e2921f..9f7011ec9 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: 89647a76a0f751668fd9ef9630c8a2ddf6fda516eadd14067a3fd98988e13210 +digest: b2ee8625cdff505db43a6c1cd1148bebac7f0281d150ddb6b1e589f7c1d621e6 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 85d556481..7f6ebde96 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -157,40 +157,120 @@ spec: variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - name: podSupplementalGroups expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - name: podFsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null - name: nonExemptContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || + !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || + variables.anyObject.securityContext.runAsUser == 0)) - name: violatingMustOrMayRunAsUser expression: | - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null + ).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsUser) ? + !variables.params.runAsUser.ranges.exists(range, + container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, + variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsUser.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsGroup expression: | - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + + variables.params.runAsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? + !variables.params.runAsGroup.ranges.exists(range, + container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, + variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsGroup.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsFsGroup expression: | - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" ) ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? + !variables.params.fsGroup.ranges.exists(range, + container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, + variables.podFsGroup >= range.min && variables.podFsGroup <= range.max) + ).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}") + : [] - name: violatingMustOrMayRunAsSupplementalGroups expression: | - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? + !variables.params.supplementalGroups.ranges.exists(range, + container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : + variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, + variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ).map(container, + "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}") + : [] - name: violatingMustRunAsNonRoot expression: | - variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + variables.nonExemptContainers.filter(container, + (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && + (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && + (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") - name: violations expression: | - variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups + variables.violatingMustRunAsNonRoot + + variables.violatingMustOrMayRunAsUser + + variables.violatingMustOrMayRunAsGroup + + variables.violatingMustOrMayRunAsFsGroup + + variables.violatingMustOrMayRunAsSupplementalGroups validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' messageExpression: 'variables.violations.join(", ")' @@ -292,7 +372,6 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) - review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 85d556481..7f6ebde96 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -157,40 +157,120 @@ spec: variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - name: podSupplementalGroups expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - name: podFsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null - name: nonExemptContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || + !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || + variables.anyObject.securityContext.runAsUser == 0)) - name: violatingMustOrMayRunAsUser expression: | - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null + ).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsUser) ? + !variables.params.runAsUser.ranges.exists(range, + container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, + variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsUser.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsGroup expression: | - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + + variables.params.runAsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? + !variables.params.runAsGroup.ranges.exists(range, + container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, + variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsGroup.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsFsGroup expression: | - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" ) ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? + !variables.params.fsGroup.ranges.exists(range, + container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, + variables.podFsGroup >= range.min && variables.podFsGroup <= range.max) + ).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}") + : [] - name: violatingMustOrMayRunAsSupplementalGroups expression: | - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? + !variables.params.supplementalGroups.ranges.exists(range, + container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : + variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, + variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ).map(container, + "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}") + : [] - name: violatingMustRunAsNonRoot expression: | - variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + variables.nonExemptContainers.filter(container, + (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && + (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && + (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") - name: violations expression: | - variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups + variables.violatingMustRunAsNonRoot + + variables.violatingMustOrMayRunAsUser + + variables.violatingMustOrMayRunAsGroup + + variables.violatingMustOrMayRunAsFsGroup + + variables.violatingMustOrMayRunAsSupplementalGroups validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' messageExpression: 'variables.violations.join(", ")' @@ -292,7 +372,6 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) - review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 99a5adcf2..1f3f38271 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -20,40 +20,120 @@ variables: variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - name: podSupplementalGroups expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - name: podFsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null - name: nonExemptContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || + !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || + variables.anyObject.securityContext.runAsUser == 0)) - name: violatingMustOrMayRunAsUser expression: | - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null + ).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsUser) ? + !variables.params.runAsUser.ranges.exists(range, + container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, + variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsUser.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsGroup expression: | - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + + variables.params.runAsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? + !variables.params.runAsGroup.ranges.exists(range, + container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, + variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsGroup.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsFsGroup expression: | - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" ) ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? + !variables.params.fsGroup.ranges.exists(range, + container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, + variables.podFsGroup >= range.min && variables.podFsGroup <= range.max) + ).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}") + : [] - name: violatingMustOrMayRunAsSupplementalGroups expression: | - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? + !variables.params.supplementalGroups.ranges.exists(range, + container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : + variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, + variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ).map(container, + "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}") + : [] - name: violatingMustRunAsNonRoot expression: | - variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + variables.nonExemptContainers.filter(container, + (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && + (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && + (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") - name: violations expression: | - variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups + variables.violatingMustRunAsNonRoot + + variables.violatingMustOrMayRunAsUser + + variables.violatingMustOrMayRunAsGroup + + variables.violatingMustOrMayRunAsFsGroup + + variables.violatingMustOrMayRunAsSupplementalGroups validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' messageExpression: 'variables.violations.join(", ")' \ No newline at end of file diff --git a/src/pod-security-policy/users/src.rego b/src/pod-security-policy/users/src.rego index decf44cf6..87565d9fc 100644 --- a/src/pod-security-policy/users/src.rego +++ b/src/pod-security-policy/users/src.rego @@ -93,7 +93,6 @@ get_field_value(field, container, _) := get_seccontext_field(field, container) # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) - review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index da252dd66..33751c9ec 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -169,40 +169,120 @@ spec: variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption))) - name: podRunAsUser expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null - name: podSupplementalGroups expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.supplementalGroups) ? variables.anyObject.spec.securityContext.supplementalGroups : null - name: podRunAsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsGroup) ? variables.anyObject.spec.securityContext.runAsGroup : null - name: podFsGroup expression: | - variables.anyObject.kind == "Pod" && has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null + has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.fsGroup) ? variables.anyObject.spec.securityContext.fsGroup : null - name: nonExemptContainers expression: | (variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, !(container.image in variables.exemptImages)) - name: missingRunAsNonRootGlobal expression: | - !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || variables.anyObject.securityContext.runAsUser == 0)) + !has(variables.anyObject.securityContext) || ((!has(variables.anyObject.securityContext.runAsNonRoot) || + !variables.anyObject.securityContext.runAsNonRoot) && (!has(variables.anyObject.securityContext.runAsUser) || + variables.anyObject.securityContext.runAsUser == 0)) - name: violatingMustOrMayRunAsUser expression: | - has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsUser) ? !variables.params.runAsUser.ranges.exists(range, container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max))).map(container, "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsUser.rule + "}") : [] + has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAs" ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsUser)) && variables.podRunAsUser == null + ).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsUser") + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsUser) ? + !variables.params.runAsUser.ranges.exists(range, + container.securityContext.runAsUser >= range.min && container.securityContext.runAsUser <= range.max) : + variables.podRunAsUser != null && !variables.params.runAsUser.ranges.exists(range, + variables.podRunAsUser >= range.min && variables.podRunAsUser <= range.max) + ) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed user. Allowed runAsUser: {ranges: [" + + variables.params.runAsUser.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsUser.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsGroup expression: | - has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? !variables.params.runAsGroup.ranges.exists(range, container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.runAsGroup.rule + "}") : [] + has(variables.params.runAsGroup) && has(variables.params.runAsGroup.rule) && (variables.params.runAsGroup.rule == "MustRunAs" || variables.params.runAsGroup.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.runAsGroup)) && variables.podRunAsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsGroup. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + + variables.params.runAsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.runAsGroup)) ? + !variables.params.runAsGroup.ranges.exists(range, + container.securityContext.runAsGroup >= range.min && container.securityContext.runAsGroup <= range.max) : + variables.podRunAsGroup != null && !variables.params.runAsGroup.ranges.exists(range, + variables.podRunAsGroup >= range.min && variables.podRunAsGroup <= range.max) + ).map(container, + "Container " + container.name + " is attempting to run as disallowed group. Allowed runAsGroup: {ranges: [" + + variables.params.runAsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.runAsGroup.rule + "}" + ) : + [] - name: violatingMustOrMayRunAsFsGroup expression: | - has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" )? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? !variables.params.fsGroup.ranges.exists(range, container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, variables.podFsGroup >= range.min && variables.podFsGroup <= range.max)).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.fsGroup.rule + "}") : [] + has(variables.params.fsGroup) && has(variables.params.fsGroup.rule) && (variables.params.fsGroup.rule == "MustRunAs" || variables.params.fsGroup.rule == "MayRunAs" ) ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.fsGroup)) && variables.podFsGroup == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}" + ) + + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.fsGroup)) ? + !variables.params.fsGroup.ranges.exists(range, + container.securityContext.fsGroup >= range.min && container.securityContext.fsGroup <= range.max) : + variables.podFsGroup != null && !variables.params.fsGroup.ranges.exists(range, + variables.podFsGroup >= range.min && variables.podFsGroup <= range.max) + ).map(container, "Container " + container.name + " is attempting to run as disallowed fsGroup. Allowed fsGroup: {ranges: [" + + variables.params.fsGroup.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.fsGroup.rule + "}") + : [] - name: violatingMustOrMayRunAsSupplementalGroups expression: | - has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? variables.nonExemptContainers.filter(container, (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null).map(container, "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") + variables.nonExemptContainers.filter(container, (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? !variables.params.supplementalGroups.ranges.exists(range, container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max))).map(container, "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + ", rule: " + variables.params.supplementalGroups.rule + "}") : [] + has(variables.params.supplementalGroups) && has(variables.params.supplementalGroups.rule) && (variables.params.supplementalGroups.rule == "MustRunAs" || variables.params.supplementalGroups.rule == "MayRunAs") ? + variables.nonExemptContainers.filter(container, + (!has(container.securityContext) || !has(container.securityContext.supplementalGroups)) && variables.podSupplementalGroups == null + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}" + ) + + variables.nonExemptContainers.filter(container, + (has(container.securityContext) && has(container.securityContext.supplementalGroups)) ? + !variables.params.supplementalGroups.ranges.exists(range, + container.securityContext.supplementalGroups.all(gp, gp >= range.min && gp <= range.max)) : + variables.podSupplementalGroups != null && !variables.params.supplementalGroups.ranges.exists(range, + variables.podSupplementalGroups.all(gp, gp >= range.min && gp <= range.max)) + ).map(container, + "Container " + container.name + " is attempting to run with disallowed supplementalGroups. Allowed supplementalGroups: {ranges: [" + + variables.params.supplementalGroups.ranges.map(range, "{max: " + string(range.max) + ", min: " + string(range.min) + "}").join(", ") + + ", rule: " + variables.params.supplementalGroups.rule + "}") + : [] - name: violatingMustRunAsNonRoot expression: | - variables.nonExemptContainers.filter(container, (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal).map(container, "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") + variables.nonExemptContainers.filter(container, + (has(variables.params.runAsUser) && has(variables.params.runAsUser.rule) && variables.params.runAsUser.rule == "MustRunAsNonRoot") && + (!has(container.securityContext) || (!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot) && + (!has(container.securityContext.runAsUser) || container.securityContext.runAsUser == 0)) && variables.missingRunAsNonRootGlobal + ).map(container, + "Container " + container.name + " is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0") - name: violations expression: | - variables.violatingMustRunAsNonRoot + variables.violatingMustOrMayRunAsUser + variables.violatingMustOrMayRunAsGroup + variables.violatingMustOrMayRunAsFsGroup + variables.violatingMustOrMayRunAsSupplementalGroups + variables.violatingMustRunAsNonRoot + + variables.violatingMustOrMayRunAsUser + + variables.violatingMustOrMayRunAsGroup + + variables.violatingMustOrMayRunAsFsGroup + + variables.violatingMustOrMayRunAsSupplementalGroups validations: - expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violations) == 0' messageExpression: 'variables.violations.join(", ")' @@ -304,7 +384,6 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) - review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } From df063ff1d100b33ffedf563f472c33690def5bec Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Tue, 1 Oct 2024 17:38:18 +0000 Subject: [PATCH 11/12] adding exempt image test Signed-off-by: Jaydip Gabani --- .../users/1.1.0/artifacthub-pkg.yml | 2 +- .../constraint.yaml | 2 ++ .../example_allowed_exempt_image.yaml | 10 +++++++ .../users/1.1.0/suite.yaml | 4 +++ .../users/1.1.0/template.yaml | 2 +- .../constraint.yaml | 2 ++ .../example_allowed_exempt_image.yaml | 10 +++++++ library/pod-security-policy/users/suite.yaml | 4 +++ .../pod-security-policy/users/template.yaml | 2 +- src/pod-security-policy/users/src.cel | 2 +- website/docs/validation/users.md | 28 ++++++++++++++++++- 11 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml create mode 100644 library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 9f7011ec9..934f24a4c 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: b2ee8625cdff505db43a6c1cd1148bebac7f0281d150ddb6b1e589f7c1d621e6 +digest: df56461fbd46bb6f56d1f197bb54a316b2727c3ba6d7c9aed01e9924576dd900 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml index e69974578..f1d0b8251 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -8,6 +8,8 @@ spec: - apiGroups: [""] kinds: ["Pod"] parameters: + exemptImages: + - nginx-exempt runAsUser: rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml new file mode 100644 index 000000000..4735857e6 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.1.0/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-allowed + labels: + app: nginx-users +spec: + containers: + - name: nginx + image: nginx-exempt diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml index 5c6e49640..b26f98f87 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/suite.yaml @@ -19,6 +19,10 @@ tests: object: samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml assertions: - violations: yes + - name: example-allowed-exempt-image + object: samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml + assertions: + - violations: no - name: update object: samples/psp-pods-allowed-user-ranges/update.yaml assertions: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index 7f6ebde96..e2d614ac4 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -154,7 +154,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: podRunAsUser expression: | has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml index e69974578..f1d0b8251 100644 --- a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/constraint.yaml @@ -8,6 +8,8 @@ spec: - apiGroups: [""] kinds: ["Pod"] parameters: + exemptImages: + - nginx-exempt runAsUser: rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: diff --git a/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml new file mode 100644 index 000000000..4735857e6 --- /dev/null +++ b/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-allowed + labels: + app: nginx-users +spec: + containers: + - name: nginx + image: nginx-exempt diff --git a/library/pod-security-policy/users/suite.yaml b/library/pod-security-policy/users/suite.yaml index 5c6e49640..b26f98f87 100644 --- a/library/pod-security-policy/users/suite.yaml +++ b/library/pod-security-policy/users/suite.yaml @@ -19,6 +19,10 @@ tests: object: samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml assertions: - violations: yes + - name: example-allowed-exempt-image + object: samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml + assertions: + - violations: no - name: update object: samples/psp-pods-allowed-user-ranges/update.yaml assertions: diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 7f6ebde96..e2d614ac4 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -154,7 +154,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: podRunAsUser expression: | has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 1f3f38271..82b98a930 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/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: podRunAsUser expression: | has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 33751c9ec..557c49067 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -166,7 +166,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: podRunAsUser expression: | has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.runAsUser) ? variables.anyObject.spec.securityContext.runAsUser : null @@ -467,6 +467,8 @@ spec: - apiGroups: [""] kinds: ["Pod"] parameters: + exemptImages: + - nginx-exempt runAsUser: rule: MustRunAs # MustRunAsNonRoot # RunAsAny ranges: @@ -596,6 +598,30 @@ Usage kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml ``` + +
+example-allowed-exempt-image + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx-users-allowed + labels: + app: nginx-users +spec: + containers: + - name: nginx + image: nginx-exempt + +``` + +Usage + +```shell +kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/users/samples/psp-pods-allowed-user-ranges/example_allowed_exempt_image.yaml +``` +
From e860d00988d8f5028697d0a137ad05f5969aa5ba Mon Sep 17 00:00:00 2001 From: Jaydip Gabani Date: Wed, 30 Oct 2024 00:13:43 +0000 Subject: [PATCH 12/12] adding matchcondition to match pod Signed-off-by: Jaydip Gabani --- .../pod-security-policy/users/1.1.0/artifacthub-pkg.yml | 2 +- .../library/pod-security-policy/users/1.1.0/template.yaml | 4 ++++ library/pod-security-policy/users/template.yaml | 4 ++++ src/pod-security-policy/users/src.cel | 3 +++ src/pod-security-policy/users/src.rego | 1 + website/docs/validation/users.md | 4 ++++ 6 files changed, 17 insertions(+), 1 deletion(-) diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml index 934f24a4c..aec6e0eb4 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/artifacthub-pkg.yml @@ -3,7 +3,7 @@ name: k8spspallowedusers displayName: Allowed Users createdAt: "2024-05-30T00:06:50Z" description: Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and `fsGroup` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups -digest: df56461fbd46bb6f56d1f197bb54a316b2727c3ba6d7c9aed01e9924576dd900 +digest: 4598260368425717a058b766c4f93f6b197e6ad817771cff1b82ffce8962eee1 license: Apache-2.0 homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/users keywords: diff --git a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml index e2d614ac4..ca7a720ac 100644 --- a/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml +++ b/artifacthub/library/pod-security-policy/users/1.1.0/template.yaml @@ -135,6 +135,9 @@ spec: code: - engine: K8sNativeValidation source: + matchConditions: + - name: "apply-to-pod" + expression: 'variables.anyObject.kind == "Pod"' variables: - name: containers expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' @@ -372,6 +375,7 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) + review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index e2d614ac4..ca7a720ac 100644 --- a/library/pod-security-policy/users/template.yaml +++ b/library/pod-security-policy/users/template.yaml @@ -135,6 +135,9 @@ spec: code: - engine: K8sNativeValidation source: + matchConditions: + - name: "apply-to-pod" + expression: 'variables.anyObject.kind == "Pod"' variables: - name: containers expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' @@ -372,6 +375,7 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) + review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/src/pod-security-policy/users/src.cel b/src/pod-security-policy/users/src.cel index 82b98a930..3d913fc26 100644 --- a/src/pod-security-policy/users/src.cel +++ b/src/pod-security-policy/users/src.cel @@ -1,3 +1,6 @@ +matchConditions: +- name: "apply-to-pod" + expression: 'variables.anyObject.kind == "Pod"' variables: - name: containers expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' diff --git a/src/pod-security-policy/users/src.rego b/src/pod-security-policy/users/src.rego index 87565d9fc..decf44cf6 100644 --- a/src/pod-security-policy/users/src.rego +++ b/src/pod-security-policy/users/src.rego @@ -93,6 +93,7 @@ get_field_value(field, container, _) := get_seccontext_field(field, container) # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) + review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value } diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 557c49067..bedc0d73b 100644 --- a/website/docs/validation/users.md +++ b/website/docs/validation/users.md @@ -147,6 +147,9 @@ spec: code: - engine: K8sNativeValidation source: + matchConditions: + - name: "apply-to-pod" + expression: 'variables.anyObject.kind == "Pod"' variables: - name: containers expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' @@ -384,6 +387,7 @@ spec: # If no container level exists, use pod level get_field_value(field, container, review) = out { not has_seccontext_field(field, container) + review.kind.kind == "Pod" pod_value := get_seccontext_field(field, review.object.spec) out := pod_value }