From 5b44a5a27f07494412a8b0acf6bca3a6f7ac86f6 Mon Sep 17 00:00:00 2001 From: Anders Eknert Date: Mon, 30 Oct 2023 16:07:33 +0100 Subject: [PATCH] Ensure OPA strict mode compliance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi Gatekeeper friends! 👋😃 In order to ensure the Gatekeeper library works with future updates of OPA, and to better catch some common mistakes in Rego policy in the future, this PR aims to fix all errors reported from `opa check --strict src`, and to make sure future changes are compliant with the OPA [strict mode](https://www.openpolicyagent.org/docs/latest/policy-language/#strict-mode) checks. The errors raised from strict mode, and which are fixed with this PR, include: * `input` must not be shadowed/assigned * Unused function args — use wildcards (`_`) in their place * Unused local assignment * Deprecated built-in functions * `re_match` -> `regex.match` * `all` -> these were not needed * `any` -> `strings.any_prefix_match` and `strings.any_suffix_match` as these were always used together with `startswith`/`endswith` The by far most noisy fix was the first one, i.e. `input` getting shadowed in basically all tests. Changed to use `inp` for a name as `in` is of course another name we don't want to shadow 😅 The changes here do not change semantics of the code. I did however also make some additional fixes where e.g. the unused function args error showed that a function wasn't needed in the first place, and so on. Naturally, all tests pass as before. Two things I'm not sure about: 1. The code introduces the `strings.any_prefix_match` and `strings.any_suffix_match` built-in functions in one policy. These were introduced in OPA v0.44.0, which is quite a few OPA and Gatekeeper versions ago. I could not find information on what the minimum version of OPA or Gatekeeper must be supported in the Rego code in this library. If needed, that change can be reverted. 2. https://github.com/open-policy-agent/gatekeeper-library mentions Versioning. Should I update the versions of each policy changed with this PR? To make sure the code stays compliant, I've added the `opa check --strict` command to execute with the `test.sh` script, before the unit tests run. Signed-off-by: Anders Eknert --- .github/workflows/workflow.yaml | 2 +- .../allowedrepos/1.0.1/artifacthub-pkg.yml | 22 + .../allowedrepos/1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 14 + .../disallowed_all.yaml | 26 + .../example_allowed.yaml | 16 + .../example_disallowed_both.yaml | 19 + .../example_disallowed_container.yaml | 12 + .../example_disallowed_initcontainer.yaml | 23 + .../general/allowedrepos/1.0.1/suite.yaml | 43 ++ .../general/allowedrepos/1.0.1/template.yaml | 46 ++ .../containerlimits/1.0.1/artifacthub-pkg.yml | 25 + .../containerlimits/1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 12 + .../example_allowed.yaml | 18 + .../example_disallowed.yaml | 18 + .../general/containerlimits/1.0.1/suite.yaml | 17 + .../containerlimits/1.0.1/template.yaml | 264 +++++++++ .../1.0.1/artifacthub-pkg.yml | 25 + .../1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 12 + .../example_allowed.yaml | 18 + .../example_disallowed.yaml | 18 + .../containerrequests/1.0.1/suite.yaml | 17 + .../containerrequests/1.0.1/template.yaml | 264 +++++++++ .../1.0.1/artifacthub-pkg.yml | 25 + .../1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 12 + .../example_allowed.yaml | 21 + .../example_disallowed.yaml | 21 + .../container-must-meet-ratio/constraint.yaml | 11 + .../example_allowed.yaml | 21 + .../example_disallowed.yaml | 21 + .../containerresourceratios/1.0.1/suite.yaml | 29 + .../1.0.1/template.yaml | 313 ++++++++++ .../disallowedtags/1.0.1/artifacthub-pkg.yml | 25 + .../disallowedtags/1.0.1/kustomization.yaml | 4 + .../constraint.yaml | 14 + .../disallowed_tag_ephemeral.yaml | 19 + .../example_allowed.yaml | 12 + .../example_disallowed_tag.yaml | 12 + ...example_exempt_image_w_disallowed_tag.yaml | 24 + .../example_no_tag.yaml | 12 + .../example_some_disallowed_tags.yaml | 30 + .../general/disallowedtags/1.0.1/suite.yaml | 33 ++ .../disallowedtags/1.0.1/template.yaml | 89 +++ .../1.0.2/artifacthub-pkg.yml | 25 + .../1.0.2/kustomization.yaml | 2 + .../constraint.yaml | 11 + ...lowed_ephemeral-storage-initContainer.yaml | 33 ++ .../example_allowed_ephemeral-storage.yaml | 20 + ...meral_storage_limit_1Pi-initContainer.yaml | 31 + ...isallowed_ephemeral_storage_limit_1Pi.yaml | 20 + ...d_ephemeral_storage_limit_unspecified.yaml | 18 + .../update.yaml | 24 + .../ephemeralstoragelimit/1.0.2/suite.yaml | 33 ++ .../ephemeralstoragelimit/1.0.2/template.yaml | 232 ++++++++ .../httpsonly/1.0.2/artifacthub-pkg.yml | 25 + .../httpsonly/1.0.2/kustomization.yaml | 2 + .../constraint.yaml | 11 + .../example_allowed.yaml | 18 + .../example_disallowed.yaml | 16 + .../ingress-https-only/constraint.yaml | 9 + .../ingress-https-only/example_allowed.yaml | 19 + .../example_disallowed.yaml | 16 + .../general/httpsonly/1.0.2/suite.yaml | 29 + .../library/general/httpsonly/1.0.2/sync.yaml | 14 + .../general/httpsonly/1.0.2/template.yaml | 71 +++ .../imagedigests/1.0.1/artifacthub-pkg.yml | 25 + .../imagedigests/1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 11 + .../disallowed_all.yaml | 26 + .../example_allowed.yaml | 12 + .../example_disallowed.yaml | 19 + .../general/imagedigests/1.0.1/suite.yaml | 31 + .../general/imagedigests/1.0.1/template.yaml | 82 +++ .../noupdateserviceaccount/1.0.1/README.md | 13 + .../1.0.1/artifacthub-pkg.yml | 22 + .../1.0.1/kustomization.yaml | 2 + .../noupdateserviceaccount/constraint.yaml | 33 ++ .../example_allowed.yaml | 31 + .../noupdateserviceaccount/1.0.1/suite.yaml | 20 + .../1.0.1/template.yaml | 106 ++++ .../replicalimits/1.0.2/artifacthub-pkg.yml | 22 + .../replicalimits/1.0.2/kustomization.yaml | 2 + .../samples/replicalimits/constraint.yaml | 13 + .../replicalimits/example_allowed.yaml | 19 + .../replicalimits/example_disallowed.yaml | 19 + .../general/replicalimits/1.0.2/suite.yaml | 17 + .../general/replicalimits/1.0.2/template.yaml | 58 ++ .../1.0.1/artifacthub-pkg.yml | 22 + .../1.0.1/kustomization.yaml | 2 + .../constraint.yaml | 18 + .../example_allowed.yaml | 14 + .../example_disallowed.yaml | 11 + .../requiredannotations/1.0.1/suite.yaml | 17 + .../requiredannotations/1.0.1/template.yaml | 59 ++ .../requiredlabels/1.0.1/artifacthub-pkg.yml | 22 + .../requiredlabels/1.0.1/kustomization.yaml | 2 + .../all-must-have-owner/constraint.yaml | 14 + .../all-must-have-owner/example_allowed.yaml | 6 + .../example_disallowed.yaml | 4 + .../general/requiredlabels/1.0.1/suite.yaml | 17 + .../requiredlabels/1.0.1/template.yaml | 68 +++ .../1.0.4/artifacthub-pkg.yml | 25 + .../1.0.4/kustomization.yaml | 2 + .../unique-ingress-host/constraint.yaml | 9 + .../unique-ingress-host/example_allowed.yaml | 27 + .../example_disallowed.yaml | 17 + .../example_disallowed2.yaml | 27 + .../example_inventory_disallowed.yaml | 17 + .../example_inventory_disallowed2.yaml | 17 + .../uniqueingresshost/1.0.4/suite.yaml | 25 + .../general/uniqueingresshost/1.0.4/sync.yaml | 17 + .../uniqueingresshost/1.0.4/template.yaml | 52 ++ .../capabilities/1.0.2/artifacthub-pkg.yml | 22 + .../capabilities/1.0.2/kustomization.yaml | 2 + .../samples/capabilities-demo/constraint.yaml | 14 + .../disallowed_ephemeral.yaml | 21 + .../capabilities-demo/example_allowed.yaml | 22 + .../capabilities-demo/example_disallowed.yaml | 21 + .../samples/capabilities-demo/update.yaml | 26 + .../capabilities/1.0.2/suite.yaml | 25 + .../capabilities/1.0.2/template.yaml | 160 ++++++ .../forbidden-sysctls/1.1.3/README.md | 36 ++ .../1.1.3/artifacthub-pkg.yml | 22 + .../1.1.3/kustomization.yaml | 2 + .../psp-forbidden-sysctls/constraint.yaml | 15 + .../example_allowed.yaml | 14 + .../example_disallowed.yaml | 16 + .../samples/psp-forbidden-sysctls/update.yaml | 21 + .../forbidden-sysctls/1.1.3/suite.yaml | 21 + .../forbidden-sysctls/1.1.3/template.yaml | 100 ++++ .../fsgroup/1.0.2/README.md | 7 + .../fsgroup/1.0.2/artifacthub-pkg.yml | 22 + .../fsgroup/1.0.2/kustomization.yaml | 2 + .../1.0.2/samples/psp-fsgroup/constraint.yaml | 14 + .../samples/psp-fsgroup/example_allowed.yaml | 17 + .../psp-fsgroup/example_disallowed.yaml | 17 + .../1.0.2/samples/psp-fsgroup/update.yaml | 22 + .../fsgroup/1.0.2/suite.yaml | 21 + .../fsgroup/1.0.2/template.yaml | 105 ++++ .../host-filesystem/1.0.2/artifacthub-pkg.yml | 22 + .../host-filesystem/1.0.2/kustomization.yaml | 2 + .../psp-host-filesystem/constraint.yaml | 13 + .../disallowed_ephemeral.yaml | 18 + .../psp-host-filesystem/example_allowed.yaml | 18 + .../example_disallowed.yaml | 18 + .../samples/psp-host-filesystem/update.yaml | 23 + .../host-filesystem/1.0.2/suite.yaml | 25 + .../host-filesystem/1.0.2/template.yaml | 148 +++++ .../1.0.2/artifacthub-pkg.yml | 22 + .../1.0.2/kustomization.yaml | 2 + .../psp-host-network-ports/constraint.yaml | 13 + .../disallowed_ephemeral.yaml | 14 + .../example_allowed.yaml | 14 + .../example_disallowed.yaml | 14 + .../psp-host-network-ports/update.yaml | 19 + .../host-network-ports/1.0.2/suite.yaml | 25 + .../host-network-ports/1.0.2/template.yaml | 118 ++++ .../proc-mount/1.0.3/README.md | 12 + .../proc-mount/1.0.3/artifacthub-pkg.yml | 22 + .../proc-mount/1.0.3/kustomization.yaml | 2 + .../samples/psp-proc-mount/constraint.yaml | 11 + .../psp-proc-mount/disallowed_ephemeral.yaml | 12 + .../psp-proc-mount/example_allowed.yaml | 12 + .../psp-proc-mount/example_disallowed.yaml | 12 + .../1.0.3/samples/psp-proc-mount/update.yaml | 17 + .../proc-mount/1.0.3/suite.yaml | 25 + .../proc-mount/1.0.3/template.yaml | 138 +++++ .../seccomp/1.0.1/artifacthub-pkg.yml | 22 + .../seccomp/1.0.1/kustomization.yaml | 2 + .../1.0.1/samples/psp-seccomp/constraint.yaml | 13 + .../psp-seccomp/disallowed_ephemeral.yaml | 12 + .../samples/psp-seccomp/example_allowed.yaml | 12 + .../samples/psp-seccomp/example_allowed2.yaml | 12 + .../psp-seccomp/example_disallowed.yaml | 12 + .../psp-seccomp/example_disallowed2.yaml | 12 + .../seccomp/1.0.1/suite.yaml | 32 ++ .../seccomp/1.0.1/template.yaml | 281 +++++++++ .../selinux/1.0.2/artifacthub-pkg.yml | 22 + .../selinux/1.0.2/kustomization.yaml | 2 + .../samples/psp-selinux-v2/constraint.yaml | 15 + .../psp-selinux-v2/disallowed_ephemeral.yaml | 16 + .../psp-selinux-v2/example_allowed.yaml | 16 + .../psp-selinux-v2/example_disallowed.yaml | 16 + .../1.0.2/samples/psp-selinux-v2/update.yaml | 21 + .../selinux/1.0.2/suite.yaml | 25 + .../selinux/1.0.2/template.yaml | 144 +++++ .../users/1.0.2/artifacthub-pkg.yml | 22 + .../users/1.0.2/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.0.2/suite.yaml | 25 + .../users/1.0.2/template.yaml | 289 ++++++++++ .../volumes/1.0.2/artifacthub-pkg.yml | 22 + .../volumes/1.0.2/kustomization.yaml | 2 + .../samples/psp-volume-types/constraint.yaml | 20 + .../psp-volume-types/example_allowed.yaml | 23 + .../psp-volume-types/example_disallowed.yaml | 24 + .../samples/psp-volume-types/update.yaml | 29 + .../volumes/1.0.2/suite.yaml | 21 + .../volumes/1.0.2/template.yaml | 64 +++ library/general/allowedrepos/template.yaml | 11 +- library/general/containerlimits/template.yaml | 6 +- .../general/containerrequests/template.yaml | 6 +- .../containerresourceratios/template.yaml | 8 +- library/general/disallowedtags/template.yaml | 9 +- .../ephemeralstoragelimit/template.yaml | 4 +- library/general/httpsonly/template.yaml | 22 +- library/general/imagedigests/template.yaml | 11 +- .../noupdateserviceaccount/template.yaml | 8 +- library/general/replicalimits/template.yaml | 4 +- .../general/requiredannotations/template.yaml | 4 +- library/general/requiredlabels/template.yaml | 11 +- .../general/uniqueingresshost/template.yaml | 6 +- .../capabilities/template.yaml | 9 +- .../forbidden-sysctls/template.yaml | 6 +- .../pod-security-policy/fsgroup/template.yaml | 4 +- .../host-filesystem/template.yaml | 4 +- .../host-network-ports/template.yaml | 6 +- .../proc-mount/template.yaml | 4 +- .../pod-security-policy/seccomp/template.yaml | 12 +- .../pod-security-policy/selinux/template.yaml | 4 +- .../pod-security-policy/users/template.yaml | 19 +- .../pod-security-policy/volumes/template.yaml | 4 +- src/general/allowedrepos/constraint.tmpl | 2 +- src/general/allowedrepos/src.rego | 9 +- src/general/allowedrepos/src_test.rego | 56 +- .../src_test.rego | 16 +- .../src_test.rego | 20 +- .../block-loadbalancer-services/src_test.rego | 8 +- .../block-nodeport-services/src_test.rego | 8 +- .../block-wildcard-ingress/src_test.rego | 20 +- src/general/containerlimits/constraint.tmpl | 2 +- src/general/containerlimits/src.rego | 4 +- src/general/containerlimits/src_test.rego | 144 ++--- src/general/containerrequests/constraint.tmpl | 2 +- src/general/containerrequests/src.rego | 4 +- src/general/containerrequests/src_test.rego | 144 ++--- .../containerresourceratios/constraint.tmpl | 2 +- src/general/containerresourceratios/src.rego | 6 +- .../containerresourceratios/src_test.rego | 192 +++---- src/general/containerresources/src_test.rego | 172 +++--- src/general/disallowanonymous/src_test.rego | 148 ++--- src/general/disallowedrepos/src_test.rego | 56 +- src/general/disallowedtags/constraint.tmpl | 2 +- src/general/disallowedtags/src.rego | 7 +- src/general/disallowedtags/src_test.rego | 84 +-- src/general/disallowinteractive/src_test.rego | 38 +- .../ephemeralstoragelimit/constraint.tmpl | 2 +- src/general/ephemeralstoragelimit/src.rego | 2 +- .../ephemeralstoragelimit/src_test.rego | 120 ++-- src/general/externalip/src_test.rego | 36 +- .../horizontalpodautoscaler/src_test.rego | 38 +- src/general/httpsonly/constraint.tmpl | 2 +- src/general/httpsonly/src.rego | 20 +- src/general/httpsonly/src_test.rego | 48 +- src/general/imagedigests/constraint.tmpl | 2 +- src/general/imagedigests/src.rego | 9 +- src/general/imagedigests/src_test.rego | 64 +-- .../noupdateserviceaccount/constraint.tmpl | 2 +- src/general/noupdateserviceaccount/src.rego | 6 +- .../noupdateserviceaccount/src_test.rego | 60 +- src/general/poddisruptionbudget/src_test.rego | 24 +- src/general/replicalimits/constraint.tmpl | 2 +- src/general/replicalimits/src.rego | 2 +- src/general/replicalimits/src_test.rego | 28 +- .../requiredannotations/constraint.tmpl | 2 +- src/general/requiredannotations/src.rego | 2 +- src/general/requiredannotations/src_test.rego | 48 +- src/general/requiredlabels/constraint.tmpl | 2 +- src/general/requiredlabels/src.rego | 9 +- src/general/requiredlabels/src_test.rego | 52 +- src/general/requiredprobes/src_test.rego | 219 +++---- src/general/storageclass/src_test.rego | 72 +-- src/general/uniqueingresshost/constraint.tmpl | 2 +- src/general/uniqueingresshost/src.rego | 4 +- src/general/uniqueingresshost/src_test.rego | 50 +- .../uniqueserviceselector/src_test.rego | 32 +- src/general/verifydeprecatedapi/src_test.rego | 8 +- .../allow-privilege-escalation/src_test.rego | 38 +- .../apparmor/src_test.rego | 44 +- .../capabilities/constraint.tmpl | 2 +- src/pod-security-policy/capabilities/src.rego | 7 +- .../capabilities/src_test.rego | 216 +++---- .../flexvolume-drivers/src_test.rego | 44 +- .../forbidden-sysctls/constraint.tmpl | 2 +- .../forbidden-sysctls/src.rego | 4 +- .../forbidden-sysctls/src_test.rego | 104 ++-- .../fsgroup/constraint.tmpl | 2 +- src/pod-security-policy/fsgroup/src.rego | 2 +- src/pod-security-policy/fsgroup/src_test.rego | 44 +- .../host-filesystem/constraint.tmpl | 2 +- .../host-filesystem/src.rego | 2 +- .../host-filesystem/src_test.rego | 104 ++-- .../host-namespaces/src_test.rego | 20 +- .../host-network-ports/constraint.tmpl | 2 +- .../host-network-ports/src.rego | 4 +- .../host-network-ports/src_test.rego | 38 +- .../privileged-containers/src_test.rego | 28 +- .../proc-mount/constraint.tmpl | 2 +- src/pod-security-policy/proc-mount/src.rego | 2 +- .../proc-mount/src_test.rego | 56 +- .../read-only-root-filesystem/src_test.rego | 24 +- .../seccomp/constraint.tmpl | 2 +- src/pod-security-policy/seccomp/src.rego | 10 +- src/pod-security-policy/seccomp/src_test.rego | 304 +++++----- .../selinux/constraint.tmpl | 2 +- src/pod-security-policy/selinux/src.rego | 2 +- src/pod-security-policy/selinux/src_test.rego | 92 +-- src/pod-security-policy/users/constraint.tmpl | 2 +- src/pod-security-policy/users/src.rego | 17 +- src/pod-security-policy/users/src_test.rego | 535 +++++++++--------- .../volumes/constraint.tmpl | 2 +- src/pod-security-policy/volumes/src.rego | 2 +- src/pod-security-policy/volumes/src_test.rego | 52 +- test.sh | 4 + website/docs/validation/allowedrepos.md | 11 +- website/docs/validation/capabilities.md | 9 +- website/docs/validation/containerlimits.md | 6 +- website/docs/validation/containerrequests.md | 6 +- .../validation/containerresourceratios.md | 8 +- website/docs/validation/disallowedtags.md | 9 +- .../docs/validation/ephemeralstoragelimit.md | 4 +- website/docs/validation/forbidden-sysctls.md | 6 +- website/docs/validation/fsgroup.md | 4 +- website/docs/validation/host-filesystem.md | 4 +- website/docs/validation/host-network-ports.md | 6 +- website/docs/validation/httpsonly.md | 22 +- website/docs/validation/imagedigests.md | 11 +- .../docs/validation/noupdateserviceaccount.md | 8 +- website/docs/validation/proc-mount.md | 4 +- website/docs/validation/replicalimits.md | 4 +- .../docs/validation/requiredannotations.md | 4 +- website/docs/validation/requiredlabels.md | 11 +- website/docs/validation/seccomp.md | 12 +- website/docs/validation/selinux.md | 4 +- website/docs/validation/uniqueingresshost.md | 6 +- website/docs/validation/users.md | 19 +- website/docs/validation/volumes.md | 4 +- 344 files changed, 8469 insertions(+), 2202 deletions(-) create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/constraint.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/disallowed_all.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_allowed.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/allowedrepos/1.0.1/template.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/constraint.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_allowed.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_disallowed.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/containerlimits/1.0.1/template.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/constraint.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_allowed.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_disallowed.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/containerrequests/1.0.1/template.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/constraint.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_allowed.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_disallowed.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/constraint.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_allowed.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_disallowed.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/containerresourceratios/1.0.1/template.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/constraint.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/disallowed_tag_ephemeral.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_allowed.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_exempt_image_w_disallowed_tag.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_no_tag.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/disallowedtags/1.0.1/template.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/constraint.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage-initContainer.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi-initContainer.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_unspecified.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/update.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/suite.yaml create mode 100644 artifacthub/library/general/ephemeralstoragelimit/1.0.2/template.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/constraint.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_allowed.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_disallowed.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/constraint.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_allowed.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_disallowed.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/suite.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/sync.yaml create mode 100644 artifacthub/library/general/httpsonly/1.0.2/template.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/constraint.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/disallowed_all.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_allowed.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_disallowed.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/imagedigests/1.0.1/template.yaml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/README.md create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/constraint.yaml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/example_allowed.yaml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/noupdateserviceaccount/1.0.1/template.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/constraint.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_allowed.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_disallowed.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/suite.yaml create mode 100644 artifacthub/library/general/replicalimits/1.0.2/template.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/constraint.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_allowed.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_disallowed.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/requiredannotations/1.0.1/template.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/constraint.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_allowed.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_disallowed.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/suite.yaml create mode 100644 artifacthub/library/general/requiredlabels/1.0.1/template.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/artifacthub-pkg.yml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/kustomization.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/constraint.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_allowed.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed2.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed2.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/suite.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/sync.yaml create mode 100644 artifacthub/library/general/uniqueingresshost/1.0.4/template.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/update.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/capabilities/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/README.md create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/update.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/template.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/README.md create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/update.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/fsgroup/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/update.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/host-filesystem/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/update.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/host-network-ports/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/README.md create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/update.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/proc-mount/1.0.3/template.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed2.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed2.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/seccomp/1.0.1/template.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/update.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/selinux/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/update.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/users/1.0.2/template.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/artifacthub-pkg.yml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/kustomization.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/constraint.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_allowed.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_disallowed.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/update.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/suite.yaml create mode 100644 artifacthub/library/pod-security-policy/volumes/1.0.2/template.yaml diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 761158645..5e9c20c0d 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -45,7 +45,7 @@ jobs: strategy: matrix: os: [ "ubuntu-latest", "macos-latest" ] - opa: [ "v0.42.2" ] + opa: [ "v0.44.0", "v0.57.1" ] name: Unit test on ${{ matrix.os }} opa ${{ matrix.opa }} steps: - name: Harden Runner diff --git a/artifacthub/library/general/allowedrepos/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/allowedrepos/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..a0c03d51f --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: k8sallowedrepos +displayName: Allowed Repositories +createdAt: "2023-10-30T20:59:57Z" +description: Requires container images to begin with a string from the specified list. +digest: eaff16a982c2d3029b280b3d4061d82b55215ac648efaafa341e25c7c77b635f +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/allowedrepos +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Allowed Repositories + Requires container images to begin with a string from the specified list. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/allowedrepos/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/allowedrepos/1.0.1/kustomization.yaml b/artifacthub/library/general/allowedrepos/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/constraint.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/constraint.yaml new file mode 100644 index 000000000..be500b5ae --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/constraint.yaml @@ -0,0 +1,14 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sAllowedRepos +metadata: + name: repo-is-openpolicyagent +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + namespaces: + - "default" + parameters: + repos: + - "openpolicyagent/" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/disallowed_all.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/disallowed_all.yaml new file mode 100644 index 000000000..bec477884 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/disallowed_all.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-disallowed +spec: + initContainers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" + containers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" + ephemeralContainers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_allowed.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_allowed.yaml new file mode 100644 index 000000000..2dc3cd246 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_allowed.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml new file mode 100644 index 000000000..4d5f3ba64 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-disallowed +spec: + initContainers: + - name: nginxinit + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" + containers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml new file mode 100644 index 000000000..face5057e --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-disallowed +spec: + containers: + - name: nginx + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml new file mode 100644 index 000000000..6f7a886c6 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-disallowed +spec: + initContainers: + - name: nginxinit + image: nginx + resources: + limits: + cpu: "100m" + memory: "30Mi" + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/general/allowedrepos/1.0.1/suite.yaml b/artifacthub/library/general/allowedrepos/1.0.1/suite.yaml new file mode 100644 index 000000000..819b8457c --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/suite.yaml @@ -0,0 +1,43 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: allowedrepos +tests: +- name: allowed-repos + template: template.yaml + constraint: samples/repo-must-be-openpolicyagent/constraint.yaml + cases: + - name: example-allowed + object: samples/repo-must-be-openpolicyagent/example_allowed.yaml + assertions: + - violations: no + - name: container-disallowed + object: samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml + assertions: + - violations: yes + message: container + - name: initcontainer-disallowed + object: samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml + assertions: + - violations: 1 + message: initContainer + - violations: 0 + message: container + - name: both-disallowed + object: samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml + assertions: + - violations: 2 + - message: initContainer + violations: 1 + - message: container + violations: 1 + - name: all-disallowed + object: samples/repo-must-be-openpolicyagent/disallowed_all.yaml + assertions: + - violations: 3 + - message: initContainer + violations: 1 + - message: container + violations: 1 + - message: ephemeralContainer + violations: 1 diff --git a/artifacthub/library/general/allowedrepos/1.0.1/template.yaml b/artifacthub/library/general/allowedrepos/1.0.1/template.yaml new file mode 100644 index 000000000..3c554d8e7 --- /dev/null +++ b/artifacthub/library/general/allowedrepos/1.0.1/template.yaml @@ -0,0 +1,46 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8sallowedrepos + annotations: + metadata.gatekeeper.sh/title: "Allowed Repositories" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires container images to begin with a string from the specified list. +spec: + crd: + spec: + names: + kind: K8sAllowedRepos + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + properties: + repos: + description: The list of prefixes a container image is allowed to have. + type: array + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8sallowedrepos + + violation[{"msg": msg}] { + container := input.review.object.spec.containers[_] + not strings.any_prefix_match(container.image, input.parameters.repos) + msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) + } + + violation[{"msg": msg}] { + container := input.review.object.spec.initContainers[_] + not strings.any_prefix_match(container.image, input.parameters.repos) + msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) + } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not strings.any_prefix_match(container.image, input.parameters.repos) + msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) + } diff --git a/artifacthub/library/general/containerlimits/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/containerlimits/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..d006729a3 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.1 +name: k8scontainerlimits +displayName: Container Limits +createdAt: "2023-10-30T20:59:58Z" +description: |- + Requires containers to have memory and CPU limits set and constrains limits to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +digest: fa0ce11ca6bacb6320053424c65d0626ee7ef96b4d359862eea031b13c8239ce +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/containerlimits +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Container Limits + Requires containers to have memory and CPU limits set and constrains limits to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/containerlimits/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/containerlimits/1.0.1/kustomization.yaml b/artifacthub/library/general/containerlimits/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/constraint.yaml b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/constraint.yaml new file mode 100644 index 000000000..2b06fd8d1 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sContainerLimits +metadata: + name: container-must-have-limits +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + cpu: "200m" + memory: "1Gi" diff --git a/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_allowed.yaml b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_allowed.yaml new file mode 100644 index 000000000..c77c3668f --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_allowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" diff --git a/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_disallowed.yaml b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_disallowed.yaml new file mode 100644 index 000000000..a5bd508a7 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/samples/container-must-have-limits/example_disallowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "2Gi" \ No newline at end of file diff --git a/artifacthub/library/general/containerlimits/1.0.1/suite.yaml b/artifacthub/library/general/containerlimits/1.0.1/suite.yaml new file mode 100644 index 000000000..c22bd5b77 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/suite.yaml @@ -0,0 +1,17 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: containerlimits +tests: +- name: container-limits + template: template.yaml + constraint: samples/container-must-have-limits/constraint.yaml + cases: + - name: example-allowed + object: samples/container-must-have-limits/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/container-must-have-limits/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/containerlimits/1.0.1/template.yaml b/artifacthub/library/general/containerlimits/1.0.1/template.yaml new file mode 100644 index 000000000..4b254c663 --- /dev/null +++ b/artifacthub/library/general/containerlimits/1.0.1/template.yaml @@ -0,0 +1,264 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8scontainerlimits + annotations: + metadata.gatekeeper.sh/title: "Container Limits" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires containers to have memory and CPU limits set and constrains + limits to be within the specified maximum values. + + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +spec: + crd: + spec: + names: + kind: K8sContainerLimits + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + 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 + cpu: + description: "The maximum allowed cpu limit on a Pod, exclusive." + type: string + memory: + description: "The maximum allowed memory limit on a Pod, exclusive." + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8scontainerlimits + + import data.lib.exempt_container.is_exempt + + missing(obj, field) = true { + not obj[field] + } + + missing(obj, field) = true { + obj[field] == "" + } + + canonify_cpu(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_cpu(orig) = new { + not is_number(orig) + endswith(orig, "m") + new := to_number(replace(orig, "m", "")) + } + + canonify_cpu(orig) = new { + not is_number(orig) + not endswith(orig, "m") + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) + new := to_number(orig) * 1000 + } + + # 10 ** 21 + mem_multiple("E") = 1000000000000000000000 { true } + + # 10 ** 18 + mem_multiple("P") = 1000000000000000000 { true } + + # 10 ** 15 + mem_multiple("T") = 1000000000000000 { true } + + # 10 ** 12 + mem_multiple("G") = 1000000000000 { true } + + # 10 ** 9 + mem_multiple("M") = 1000000000 { true } + + # 10 ** 6 + mem_multiple("k") = 1000000 { true } + + # 10 ** 3 + mem_multiple("") = 1000 { true } + + # Kubernetes accepts millibyte precision when it probably shouldn't. + # https://github.com/kubernetes/kubernetes/issues/28741 + # 10 ** 0 + mem_multiple("m") = 1 { true } + + # 1000 * 2 ** 10 + mem_multiple("Ki") = 1024000 { true } + + # 1000 * 2 ** 20 + mem_multiple("Mi") = 1048576000 { true } + + # 1000 * 2 ** 30 + mem_multiple("Gi") = 1073741824000 { true } + + # 1000 * 2 ** 40 + mem_multiple("Ti") = 1099511627776000 { true } + + # 1000 * 2 ** 50 + mem_multiple("Pi") = 1125899906842624000 { true } + + # 1000 * 2 ** 60 + mem_multiple("Ei") = 1152921504606846976000 { true } + + get_suffix(mem) = suffix { + not is_string(mem) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 0 + suffix := substring(mem, count(mem) - 1, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + suffix := substring(mem, count(mem) - 2, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + not mem_multiple(substring(mem, count(mem) - 2, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 0 + suffix := "" + } + + canonify_mem(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_mem(orig) = new { + not is_number(orig) + suffix := get_suffix(orig) + raw := replace(orig, suffix, "") + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) + new := to_number(raw) * mem_multiple(suffix) + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "containers"}] + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "initContainers"}] + } + + # Ephemeral containers not checked as it is not possible to set field. + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.limits.cpu + not canonify_cpu(cpu_orig) + msg := sprintf("container <%v> cpu limit <%v> could not be parsed", [container.name, cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.limits.memory + not canonify_mem(mem_orig) + msg := sprintf("container <%v> memory limit <%v> could not be parsed", [container.name, mem_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources.limits + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.limits, "cpu") + msg := sprintf("container <%v> has no cpu limit", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.limits, "memory") + msg := sprintf("container <%v> has no memory limit", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.limits.cpu + cpu := canonify_cpu(cpu_orig) + max_cpu_orig := input.parameters.cpu + max_cpu := canonify_cpu(max_cpu_orig) + cpu > max_cpu + msg := sprintf("container <%v> cpu limit <%v> is higher than the maximum allowed of <%v>", [container.name, cpu_orig, max_cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.limits.memory + mem := canonify_mem(mem_orig) + max_mem_orig := input.parameters.memory + max_mem := canonify_mem(max_mem_orig) + mem > max_mem + msg := sprintf("container <%v> memory limit <%v> is higher than the maximum allowed of <%v>", [container.name, mem_orig, max_mem_orig]) + } + libs: + - | + 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/artifacthub/library/general/containerrequests/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/containerrequests/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..f6318008a --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.1 +name: k8scontainerrequests +displayName: Container Requests +createdAt: "2023-10-30T20:59:58Z" +description: |- + Requires containers to have memory and CPU requests set and constrains requests to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +digest: f8cb14a41eb63e15bd55178cdd4b3c7c4f7e9ec1aebd296ff36f51b201113254 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/containerrequests +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Container Requests + Requires containers to have memory and CPU requests set and constrains requests to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/containerrequests/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/containerrequests/1.0.1/kustomization.yaml b/artifacthub/library/general/containerrequests/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/constraint.yaml b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/constraint.yaml new file mode 100644 index 000000000..1bcc3572f --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sContainerRequests +metadata: + name: container-must-have-requests +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + cpu: "200m" + memory: "1Gi" diff --git a/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_allowed.yaml b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_allowed.yaml new file mode 100644 index 000000000..48af2a4b3 --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_allowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + requests: + cpu: "100m" + memory: "1Gi" diff --git a/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_disallowed.yaml b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_disallowed.yaml new file mode 100644 index 000000000..126b8631b --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/samples/container-must-have-requests/example_disallowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + requests: + cpu: "100m" + memory: "2Gi" diff --git a/artifacthub/library/general/containerrequests/1.0.1/suite.yaml b/artifacthub/library/general/containerrequests/1.0.1/suite.yaml new file mode 100644 index 000000000..1c4b224eb --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/suite.yaml @@ -0,0 +1,17 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: containerrequests +tests: +- name: container-requests + template: template.yaml + constraint: samples/container-must-have-requests/constraint.yaml + cases: + - name: example-allowed + object: samples/container-must-have-requests/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/container-must-have-requests/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/containerrequests/1.0.1/template.yaml b/artifacthub/library/general/containerrequests/1.0.1/template.yaml new file mode 100644 index 000000000..a67e8b786 --- /dev/null +++ b/artifacthub/library/general/containerrequests/1.0.1/template.yaml @@ -0,0 +1,264 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8scontainerrequests + annotations: + metadata.gatekeeper.sh/title: "Container Requests" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires containers to have memory and CPU requests set and constrains + requests to be within the specified maximum values. + + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +spec: + crd: + spec: + names: + kind: K8sContainerRequests + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + 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 + cpu: + description: "The maximum allowed cpu request on a Pod, exclusive." + type: string + memory: + description: "The maximum allowed memory request on a Pod, exclusive." + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8scontainerrequests + + import data.lib.exempt_container.is_exempt + + missing(obj, field) = true { + not obj[field] + } + + missing(obj, field) = true { + obj[field] == "" + } + + canonify_cpu(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_cpu(orig) = new { + not is_number(orig) + endswith(orig, "m") + new := to_number(replace(orig, "m", "")) + } + + canonify_cpu(orig) = new { + not is_number(orig) + not endswith(orig, "m") + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) + new := to_number(orig) * 1000 + } + + # 10 ** 21 + mem_multiple("E") = 1000000000000000000000 { true } + + # 10 ** 18 + mem_multiple("P") = 1000000000000000000 { true } + + # 10 ** 15 + mem_multiple("T") = 1000000000000000 { true } + + # 10 ** 12 + mem_multiple("G") = 1000000000000 { true } + + # 10 ** 9 + mem_multiple("M") = 1000000000 { true } + + # 10 ** 6 + mem_multiple("k") = 1000000 { true } + + # 10 ** 3 + mem_multiple("") = 1000 { true } + + # Kubernetes accepts millibyte precision when it probably shouldn't. + # https://github.com/kubernetes/kubernetes/issues/28741 + # 10 ** 0 + mem_multiple("m") = 1 { true } + + # 1000 * 2 ** 10 + mem_multiple("Ki") = 1024000 { true } + + # 1000 * 2 ** 20 + mem_multiple("Mi") = 1048576000 { true } + + # 1000 * 2 ** 30 + mem_multiple("Gi") = 1073741824000 { true } + + # 1000 * 2 ** 40 + mem_multiple("Ti") = 1099511627776000 { true } + + # 1000 * 2 ** 50 + mem_multiple("Pi") = 1125899906842624000 { true } + + # 1000 * 2 ** 60 + mem_multiple("Ei") = 1152921504606846976000 { true } + + get_suffix(mem) = suffix { + not is_string(mem) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 0 + suffix := substring(mem, count(mem) - 1, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + suffix := substring(mem, count(mem) - 2, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + not mem_multiple(substring(mem, count(mem) - 2, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 0 + suffix := "" + } + + canonify_mem(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_mem(orig) = new { + not is_number(orig) + suffix := get_suffix(orig) + raw := replace(orig, suffix, "") + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) + new := to_number(raw) * mem_multiple(suffix) + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "containers"}] + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "initContainers"}] + } + + # Ephemeral containers not checked as it is not possible to set field. + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.requests.cpu + not canonify_cpu(cpu_orig) + msg := sprintf("container <%v> cpu request <%v> could not be parsed", [container.name, cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.requests.memory + not canonify_mem(mem_orig) + msg := sprintf("container <%v> memory request <%v> could not be parsed", [container.name, mem_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources + msg := sprintf("container <%v> has no resource requests", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources.requests + msg := sprintf("container <%v> has no resource requests", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.requests, "cpu") + msg := sprintf("container <%v> has no cpu request", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.requests, "memory") + msg := sprintf("container <%v> has no memory request", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.requests.cpu + cpu := canonify_cpu(cpu_orig) + max_cpu_orig := input.parameters.cpu + max_cpu := canonify_cpu(max_cpu_orig) + cpu > max_cpu + msg := sprintf("container <%v> cpu request <%v> is higher than the maximum allowed of <%v>", [container.name, cpu_orig, max_cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.requests.memory + mem := canonify_mem(mem_orig) + max_mem_orig := input.parameters.memory + max_mem := canonify_mem(max_mem_orig) + mem > max_mem + msg := sprintf("container <%v> memory request <%v> is higher than the maximum allowed of <%v>", [container.name, mem_orig, max_mem_orig]) + } + libs: + - | + 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/artifacthub/library/general/containerresourceratios/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/containerresourceratios/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..1b62d50cb --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.1 +name: k8scontainerratios +displayName: Container Ratios +createdAt: "2023-10-30T20:59:58Z" +description: |- + Sets a maximum ratio for container resource limits to requests. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +digest: 1a85e6bfea3820f092cdea95dfdb9d8b14fb48d90e565b0e432d5faca597b4d1 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/containerresourceratios +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Container Ratios + Sets a maximum ratio for container resource limits to requests. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/containerresourceratios/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/kustomization.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/constraint.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/constraint.yaml new file mode 100644 index 000000000..c49c5bd2c --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/constraint.yaml @@ -0,0 +1,12 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sContainerRatios +metadata: + name: container-must-meet-memory-and-cpu-ratio +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + ratio: "1" + cpuRatio: "10" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_allowed.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_allowed.yaml new file mode 100644 index 000000000..700786f9e --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_allowed.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "4" + memory: "2Gi" + requests: + cpu: "1" + memory: "2Gi" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_disallowed.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_disallowed.yaml new file mode 100644 index 000000000..bf8b3e87c --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-memory-and-cpu-ratio/example_disallowed.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "4" + memory: "2Gi" + requests: + cpu: "100m" + memory: "2Gi" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/constraint.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/constraint.yaml new file mode 100644 index 000000000..db7ac53e6 --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/constraint.yaml @@ -0,0 +1,11 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sContainerRatios +metadata: + name: container-must-meet-ratio +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + ratio: "2" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_allowed.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_allowed.yaml new file mode 100644 index 000000000..eb8ba6860 --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_allowed.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "200m" + memory: "200Mi" + requests: + cpu: "100m" + memory: "100Mi" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_disallowed.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_disallowed.yaml new file mode 100644 index 000000000..4b3b12715 --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/samples/container-must-meet-ratio/example_disallowed.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "800m" + memory: "2Gi" + requests: + cpu: "100m" + memory: "100Mi" diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/suite.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/suite.yaml new file mode 100644 index 000000000..8df0686b7 --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/suite.yaml @@ -0,0 +1,29 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: containerresourceratios +tests: + - name: memory-ratio-only + template: template.yaml + constraint: samples/container-must-meet-ratio/constraint.yaml + cases: + - name: example-allowed + object: samples/container-must-meet-ratio/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/container-must-meet-ratio/example_disallowed.yaml + assertions: + - violations: yes + - name: memory-and-cpu-ratios + template: template.yaml + constraint: samples/container-must-meet-memory-and-cpu-ratio/constraint.yaml + cases: + - name: example-allowed + object: samples/container-must-meet-memory-and-cpu-ratio/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/container-must-meet-memory-and-cpu-ratio/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/containerresourceratios/1.0.1/template.yaml b/artifacthub/library/general/containerresourceratios/1.0.1/template.yaml new file mode 100644 index 000000000..94a9753aa --- /dev/null +++ b/artifacthub/library/general/containerresourceratios/1.0.1/template.yaml @@ -0,0 +1,313 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8scontainerratios + annotations: + metadata.gatekeeper.sh/title: "Container Ratios" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Sets a maximum ratio for container resource limits to requests. + + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +spec: + crd: + spec: + names: + kind: K8sContainerRatios + validation: + openAPIV3Schema: + type: object + 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 + ratio: + type: string + description: >- + The maximum allowed ratio of `resources.limits` to + `resources.requests` on a container. + cpuRatio: + type: string + description: >- + The maximum allowed ratio of `resources.limits.cpu` to + `resources.requests.cpu` on a container. If not specified, + equal to `ratio`. + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8scontainerratios + + import data.lib.exempt_container.is_exempt + + missing(obj, field) = true { + not obj[field] + } + + missing(obj, field) = true { + obj[field] == "" + } + + canonify_cpu(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_cpu(orig) = new { + not is_number(orig) + endswith(orig, "m") + new := to_number(replace(orig, "m", "")) + } + + canonify_cpu(orig) = new { + not is_number(orig) + not endswith(orig, "m") + regex.match("^[0-9]+$", orig) + new := to_number(orig) * 1000 + } + + canonify_cpu(orig) = new { + not is_number(orig) + not endswith(orig, "m") + regex.match("^[0-9]+[.][0-9]+$", orig) + new := to_number(orig) * 1000 + } + + # 10 ** 21 + mem_multiple("E") = 1000000000000000000000 { true } + + # 10 ** 18 + mem_multiple("P") = 1000000000000000000 { true } + + # 10 ** 15 + mem_multiple("T") = 1000000000000000 { true } + + # 10 ** 12 + mem_multiple("G") = 1000000000000 { true } + + # 10 ** 9 + mem_multiple("M") = 1000000000 { true } + + # 10 ** 6 + mem_multiple("k") = 1000000 { true } + + # 10 ** 3 + mem_multiple("") = 1000 { true } + + # Kubernetes accepts millibyte precision when it probably shouldn't. + # https://github.com/kubernetes/kubernetes/issues/28741 + # 10 ** 0 + mem_multiple("m") = 1 { true } + + # 1000 * 2 ** 10 + mem_multiple("Ki") = 1024000 { true } + + # 1000 * 2 ** 20 + mem_multiple("Mi") = 1048576000 { true } + + # 1000 * 2 ** 30 + mem_multiple("Gi") = 1073741824000 { true } + + # 1000 * 2 ** 40 + mem_multiple("Ti") = 1099511627776000 { true } + + # 1000 * 2 ** 50 + mem_multiple("Pi") = 1125899906842624000 { true } + + # 1000 * 2 ** 60 + mem_multiple("Ei") = 1152921504606846976000 { true } + + get_suffix(mem) = suffix { + not is_string(mem) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 0 + suffix := substring(mem, count(mem) - 1, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + suffix := substring(mem, count(mem) - 2, -1) + mem_multiple(suffix) + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) > 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + not mem_multiple(substring(mem, count(mem) - 2, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 1 + not mem_multiple(substring(mem, count(mem) - 1, -1)) + suffix := "" + } + + get_suffix(mem) = suffix { + is_string(mem) + count(mem) == 0 + suffix := "" + } + + canonify_mem(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_mem(orig) = new { + not is_number(orig) + suffix := get_suffix(orig) + raw := replace(orig, suffix, "") + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) + new := to_number(raw) * mem_multiple(suffix) + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "containers"}] + } + + violation[{"msg": msg}] { + general_violation[{"msg": msg, "field": "initContainers"}] + } + + # Ephemeral containers not checked as it is not possible to set field. + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.limits.cpu + not canonify_cpu(cpu_orig) + msg := sprintf("container <%v> cpu limit <%v> could not be parsed", [container.name, cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.limits.memory + not canonify_mem(mem_orig) + msg := sprintf("container <%v> memory limit <%v> could not be parsed", [container.name, mem_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_orig := container.resources.requests.cpu + not canonify_cpu(cpu_orig) + msg := sprintf("container <%v> cpu request <%v> could not be parsed", [container.name, cpu_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_orig := container.resources.requests.memory + not canonify_mem(mem_orig) + msg := sprintf("container <%v> memory request <%v> could not be parsed", [container.name, mem_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources.limits + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.limits, "cpu") + msg := sprintf("container <%v> has no cpu limit", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.limits, "memory") + msg := sprintf("container <%v> has no memory limit", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources.requests + msg := sprintf("container <%v> has no resource requests", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.requests, "cpu") + msg := sprintf("container <%v> has no cpu request", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.requests, "memory") + msg := sprintf("container <%v> has no memory request", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + cpu_limits_orig := container.resources.limits.cpu + cpu_limits := canonify_cpu(cpu_limits_orig) + cpu_requests_orig := container.resources.requests.cpu + cpu_requests := canonify_cpu(cpu_requests_orig) + cpu_ratio := object.get(input.parameters, "cpuRatio", input.parameters.ratio) + to_number(cpu_limits) > to_number(cpu_ratio) * to_number(cpu_requests) + msg := sprintf("container <%v> cpu limit <%v> is higher than the maximum allowed ratio of <%v>", [container.name, cpu_limits_orig, cpu_ratio]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + mem_limits_orig := container.resources.limits.memory + mem_requests_orig := container.resources.requests.memory + mem_limits := canonify_mem(mem_limits_orig) + mem_requests := canonify_mem(mem_requests_orig) + mem_ratio := input.parameters.ratio + to_number(mem_limits) > to_number(mem_ratio) * to_number(mem_requests) + msg := sprintf("container <%v> memory limit <%v> is higher than the maximum allowed ratio of <%v>", [container.name, mem_limits_orig, mem_ratio]) + } + libs: + - | + 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/artifacthub/library/general/disallowedtags/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/disallowedtags/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..191ca7b00 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.1 +name: k8sdisallowedtags +displayName: Disallow tags +createdAt: "2023-10-30T20:59:59Z" +description: |- + Requires container images to have an image tag different from the ones in the specified list. + https://kubernetes.io/docs/concepts/containers/images/#image-names +digest: c678f10ef73f11162ccc8ba6a5891cd033168273e386db9d5634179dc4cafa3c +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/disallowedtags +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Disallow tags + Requires container images to have an image tag different from the ones in the specified list. + https://kubernetes.io/docs/concepts/containers/images/#image-names +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/disallowedtags/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/disallowedtags/1.0.1/kustomization.yaml b/artifacthub/library/general/disallowedtags/1.0.1/kustomization.yaml new file mode 100644 index 000000000..a2469fa0a --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - template.yaml diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/constraint.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/constraint.yaml new file mode 100644 index 000000000..cceb50565 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/constraint.yaml @@ -0,0 +1,14 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sDisallowedTags +metadata: + name: container-image-must-not-have-latest-tag +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + namespaces: + - "default" + parameters: + tags: ["latest"] + exemptImages: ["openpolicyagent/opa-exp:latest", "openpolicyagent/opa-exp2:latest"] diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/disallowed_tag_ephemeral.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/disallowed_tag_ephemeral.yaml new file mode 100644 index 000000000..66db83c15 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/disallowed_tag_ephemeral.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed-ephemeral +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_allowed.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_allowed.yaml new file mode 100644 index 000000000..cc6407401 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml new file mode 100644 index 000000000..1c689315f --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed-2 +spec: + containers: + - name: opa + image: openpolicyagent/opa:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_exempt_image_w_disallowed_tag.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_exempt_image_w_disallowed_tag.yaml new file mode 100644 index 000000000..2bd249fec --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_exempt_image_w_disallowed_tag.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-exempt-allowed +spec: + containers: + - name: opa-exp + image: openpolicyagent/opa-exp:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" + - name: opa-init + image: openpolicyagent/init:v1 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + - name: opa-exp2 + image: openpolicyagent/opa-exp2:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_no_tag.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_no_tag.yaml new file mode 100644 index 000000000..3da276bf8 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_no_tag.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed +spec: + containers: + - name: opa + image: openpolicyagent/opa + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml new file mode 100644 index 000000000..3596fc0c4 --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed-3 +spec: + containers: + - name: opa + image: openpolicyagent/opa-exp:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" + - name: opa-init + image: openpolicyagent/init:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" + - name: opa-exp2 + image: openpolicyagent/opa-exp2:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" + - name: opa-monitor + image: openpolicyagent/monitor:latest + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/disallowedtags/1.0.1/suite.yaml b/artifacthub/library/general/disallowedtags/1.0.1/suite.yaml new file mode 100644 index 000000000..3f67b403c --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/suite.yaml @@ -0,0 +1,33 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: disallowedtags +tests: +- name: disallowed-tags + template: template.yaml + constraint: samples/container-image-must-not-have-latest-tag/constraint.yaml + cases: + - name: allowed + object: samples/container-image-must-not-have-latest-tag/example_allowed.yaml + assertions: + - violations: no + - name: exempt-images-with-disallowed-tags + object: samples/container-image-must-not-have-latest-tag/example_exempt_image_w_disallowed_tag.yaml + assertions: + - violations: no + - name: no-tag + object: samples/container-image-must-not-have-latest-tag/example_no_tag.yaml + assertions: + - violations: yes + - name: single-disallowed-tag + object: samples/container-image-must-not-have-latest-tag/example_disallowed_tag.yaml + assertions: + - violations: yes + - name: single-disallowed-tag-ephemeral + object: samples/container-image-must-not-have-latest-tag/disallowed_tag_ephemeral.yaml + assertions: + - violations: yes + - name: some-disallow-tags + object: samples/container-image-must-not-have-latest-tag/example_some_disallowed_tags.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/disallowedtags/1.0.1/template.yaml b/artifacthub/library/general/disallowedtags/1.0.1/template.yaml new file mode 100644 index 000000000..43651dd0c --- /dev/null +++ b/artifacthub/library/general/disallowedtags/1.0.1/template.yaml @@ -0,0 +1,89 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8sdisallowedtags + annotations: + metadata.gatekeeper.sh/title: "Disallow tags" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires container images to have an image tag different from the ones in + the specified list. + + https://kubernetes.io/docs/concepts/containers/images/#image-names +spec: + crd: + spec: + names: + kind: K8sDisallowedTags + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + 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 + tags: + type: array + description: Disallowed container image tags. + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8sdisallowedtags + + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg}] { + container := input_containers[_] + not is_exempt(container) + tags := [tag_with_prefix | tag := input.parameters.tags[_]; tag_with_prefix := concat(":", ["", tag])] + strings.any_suffix_match(container.image, tags) + msg := sprintf("container <%v> uses a disallowed tag <%v>; disallowed tags are %v", [container.name, container.image, input.parameters.tags]) + } + + violation[{"msg": msg}] { + container := input_containers[_] + not is_exempt(container) + not contains(container.image, ":") + msg := sprintf("container <%v> didn't specify an image tag <%v>", [container.name, container.image]) + } + + 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.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/artifacthub/library/general/ephemeralstoragelimit/1.0.2/artifacthub-pkg.yml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..53ba3245a --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.2 +name: k8scontainerephemeralstoragelimit +displayName: Container ephemeral storage limit +createdAt: "2023-10-30T20:59:59Z" +description: |- + Requires containers to have an ephemeral storage limit set and constrains the limit to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +digest: d176d78005ddec48c2b46cf33e246eba8089425e95058c29828843983de37f4d +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/ephemeralstoragelimit +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Container ephemeral storage limit + Requires containers to have an ephemeral storage limit set and constrains the limit to be within the specified maximum values. + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/ephemeralstoragelimit/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/kustomization.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/constraint.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/constraint.yaml new file mode 100644 index 000000000..4575bdf60 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/constraint.yaml @@ -0,0 +1,11 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sContainerEphemeralStorageLimit +metadata: + name: container-ephemeral-storage-limit +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + ephemeral-storage: "500Mi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage-initContainer.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage-initContainer.yaml new file mode 100644 index 000000000..fe1b7bac0 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage-initContainer.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + initContainers: + - name: init-opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + ephemeral-storage: "100Mi" + + + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + ephemeral-storage: "100Mi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage.yaml new file mode 100644 index 000000000..3c1f5ce9e --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + + ephemeral-storage: "100Mi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi-initContainer.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi-initContainer.yaml new file mode 100644 index 000000000..05d512d3c --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi-initContainer.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + initContainers: + - name: init-opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + ephemeral-storage: "1Pi" + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + ephemeral-storage: "100Mi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi.yaml new file mode 100644 index 000000000..7dae0395b --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + + ephemeral-storage: "1Pi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_unspecified.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_unspecified.yaml new file mode 100644 index 000000000..6e81b1118 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_unspecified.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "2Gi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/update.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/update.yaml new file mode 100644 index 000000000..c0ff27893 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/samples/container-must-have-ephemeral-storage-limit/update.yaml @@ -0,0 +1,24 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo + spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + resources: + limits: + cpu: "100m" + memory: "1Gi" + ephemeral-storage: "1Pi" diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/suite.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/suite.yaml new file mode 100644 index 000000000..a6b99410d --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/suite.yaml @@ -0,0 +1,33 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: ephemeral-storage-limit +tests: +- name: ephemeral-storage-limit + template: template.yaml + constraint: samples/container-must-have-ephemeral-storage-limit/constraint.yaml + cases: + - name: ephemeral-storage-limit-100Mi + object: samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage.yaml + assertions: + - violations: no + - name: ephemeral-storage-limit-initContainer-100Mi + object: samples/container-must-have-ephemeral-storage-limit/example_allowed_ephemeral-storage-initContainer.yaml + assertions: + - violations: no + - name: ephemeral-storage-limit-unspecified + object: samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_unspecified.yaml + assertions: + - violations: yes + - name: ephemeral-storage-limit-1Pi + object: samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi.yaml + assertions: + - violations: yes + - name: ephemeral-storage-limit-initContainer-1Pi + object: samples/container-must-have-ephemeral-storage-limit/example_disallowed_ephemeral_storage_limit_1Pi-initContainer.yaml + assertions: + - violations: yes + - name: ephemeral-storage-limit-update + object: samples/container-must-have-ephemeral-storage-limit/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/general/ephemeralstoragelimit/1.0.2/template.yaml b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/template.yaml new file mode 100644 index 000000000..a9dca71d2 --- /dev/null +++ b/artifacthub/library/general/ephemeralstoragelimit/1.0.2/template.yaml @@ -0,0 +1,232 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8scontainerephemeralstoragelimit + annotations: + metadata.gatekeeper.sh/title: "Container ephemeral storage limit" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Requires containers to have an ephemeral storage limit set and constrains + the limit to be within the specified maximum values. + + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +spec: + crd: + spec: + names: + kind: K8sContainerEphemeralStorageLimit + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + 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 + ephemeral-storage: + description: "The maximum allowed ephemeral storage limit on a Pod, exclusive." + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8scontainerephemeralstoragelimit + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + missing(obj, field) = true { + not obj[field] + } + + missing(obj, field) = true { + obj[field] == "" + } + + has_field(object, field) = true { + object[field] + } + + # 10 ** 21 + storage_multiple("E") = 1000000000000000000000 { true } + + # 10 ** 18 + storage_multiple("P") = 1000000000000000000 { true } + + # 10 ** 15 + storage_multiple("T") = 1000000000000000 { true } + + # 10 ** 12 + storage_multiple("G") = 1000000000000 { true } + + # 10 ** 9 + storage_multiple("M") = 1000000000 { true } + + # 10 ** 6 + storage_multiple("k") = 1000000 { true } + + # 10 ** 3 + storage_multiple("") = 1000 { true } + + # Kubernetes accepts millibyte precision when it probably shouldn't. + # https://github.com/kubernetes/kubernetes/issues/28741 + # 10 ** 0 + storage_multiple("m") = 1 { true } + + # 1000 * 2 ** 10 + storage_multiple("Ki") = 1024000 { true } + + # 1000 * 2 ** 20 + storage_multiple("Mi") = 1048576000 { true } + + # 1000 * 2 ** 30 + storage_multiple("Gi") = 1073741824000 { true } + + # 1000 * 2 ** 40 + storage_multiple("Ti") = 1099511627776000 { true } + + # 1000 * 2 ** 50 + storage_multiple("Pi") = 1125899906842624000 { true } + + # 1000 * 2 ** 60 + storage_multiple("Ei") = 1152921504606846976000 { true } + + get_suffix(storage) = suffix { + not is_string(storage) + suffix := "" + } + + get_suffix(storage) = suffix { + is_string(storage) + count(storage) > 0 + suffix := substring(storage, count(storage) - 1, -1) + storage_multiple(suffix) + } + + get_suffix(storage) = suffix { + is_string(storage) + count(storage) > 1 + suffix := substring(storage, count(storage) - 2, -1) + storage_multiple(suffix) + } + + get_suffix(storage) = suffix { + is_string(storage) + count(storage) > 1 + not storage_multiple(substring(storage, count(storage) - 1, -1)) + not storage_multiple(substring(storage, count(storage) - 2, -1)) + suffix := "" + } + + get_suffix(storage) = suffix { + is_string(storage) + count(storage) == 1 + not storage_multiple(substring(storage, count(storage) - 1, -1)) + suffix := "" + } + + get_suffix(storage) = suffix { + is_string(storage) + count(storage) == 0 + suffix := "" + } + + canonify_storage(orig) = new { + is_number(orig) + new := orig * 1000 + } + + canonify_storage(orig) = new { + not is_number(orig) + suffix := get_suffix(orig) + raw := replace(orig, suffix, "") + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) + new := to_number(raw) * storage_multiple(suffix) + } + + violation[{"msg": msg}] { + # spec.containers.resources.limits["ephemeral-storage"] field is immutable. + not is_update(input.review) + + general_violation[{"msg": msg, "field": "containers"}] + } + + violation[{"msg": msg}] { + not is_update(input.review) + general_violation[{"msg": msg, "field": "initContainers"}] + } + + # Ephemeral containers not checked as it is not possible to set field. + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + storage_orig := container.resources.limits["ephemeral-storage"] + not canonify_storage(storage_orig) + msg := sprintf("container <%v> ephemeral-storage limit <%v> could not be parsed", [container.name, storage_orig]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + not container.resources.limits + msg := sprintf("container <%v> has no resource limits", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + missing(container.resources.limits, "ephemeral-storage") + msg := sprintf("container <%v> has no ephemeral-storage limit", [container.name]) + } + + general_violation[{"msg": msg, "field": field}] { + container := input.review.object.spec[field][_] + not is_exempt(container) + storage_orig := container.resources.limits["ephemeral-storage"] + storage := canonify_storage(storage_orig) + max_storage_orig := input.parameters["ephemeral-storage"] + max_storage := canonify_storage(max_storage_orig) + storage > max_storage + msg := sprintf("container <%v> ephemeral-storage limit <%v> is higher than the maximum allowed of <%v>", [container.name, storage_orig, max_storage_orig]) + } + 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/artifacthub/library/general/httpsonly/1.0.2/artifacthub-pkg.yml b/artifacthub/library/general/httpsonly/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..7174a9b3c --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.2 +name: k8shttpsonly +displayName: HTTPS Only +createdAt: "2023-10-30T21:00:00Z" +description: |- + Requires Ingress resources to be HTTPS only. Ingress resources must include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. By default a valid TLS {} configuration is required, this can be made optional by setting the `tlsOptional` parameter to `true`. + https://kubernetes.io/docs/concepts/services-networking/ingress/#tls +digest: 1cacfb5327a12bdd71767fe5e82007e73f233b0edd7f9555722d865c8b9a9c10 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/httpsonly +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # HTTPS Only + Requires Ingress resources to be HTTPS only. Ingress resources must include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. By default a valid TLS {} configuration is required, this can be made optional by setting the `tlsOptional` parameter to `true`. + https://kubernetes.io/docs/concepts/services-networking/ingress/#tls +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/httpsonly/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/httpsonly/1.0.2/kustomization.yaml b/artifacthub/library/general/httpsonly/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/constraint.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/constraint.yaml new file mode 100644 index 000000000..a92540d91 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/constraint.yaml @@ -0,0 +1,11 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sHttpsOnly +metadata: + name: ingress-https-only-tls-optional +spec: + match: + kinds: + - apiGroups: ["extensions", "networking.k8s.io"] + kinds: ["Ingress"] + parameters: + tlsOptional: true diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_allowed.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_allowed.yaml new file mode 100644 index 000000000..27a94ee8b --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_allowed.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-demo-allowed-tls-optional + annotations: + kubernetes.io/ingress.allow-http: "false" +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_disallowed.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_disallowed.yaml new file mode 100644 index 000000000..c6097a9f7 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only-tls-optional/example_disallowed.yaml @@ -0,0 +1,16 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-demo-disallowed-tls-optional +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/constraint.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/constraint.yaml new file mode 100644 index 000000000..e3bd9ca97 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/constraint.yaml @@ -0,0 +1,9 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sHttpsOnly +metadata: + name: ingress-https-only +spec: + match: + kinds: + - apiGroups: ["extensions", "networking.k8s.io"] + kinds: ["Ingress"] diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_allowed.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_allowed.yaml new file mode 100644 index 000000000..4d48fdc3a --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_allowed.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-demo-allowed + annotations: + kubernetes.io/ingress.allow-http: "false" +spec: + tls: [{}] + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_disallowed.yaml b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_disallowed.yaml new file mode 100644 index 000000000..730ec1dc4 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/samples/ingress-https-only/example_disallowed.yaml @@ -0,0 +1,16 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-demo-disallowed +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/httpsonly/1.0.2/suite.yaml b/artifacthub/library/general/httpsonly/1.0.2/suite.yaml new file mode 100644 index 000000000..a40395524 --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/suite.yaml @@ -0,0 +1,29 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: httpsonly +tests: +- name: tls-required + template: template.yaml + constraint: samples/ingress-https-only/constraint.yaml + cases: + - name: example-allowed + object: samples/ingress-https-only/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/ingress-https-only/example_disallowed.yaml + assertions: + - violations: yes +- name: tls-optional + template: template.yaml + constraint: samples/ingress-https-only-tls-optional/constraint.yaml + cases: + - name: example-allowed-tls-optional + object: samples/ingress-https-only-tls-optional/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed-tls-optional + object: samples/ingress-https-only-tls-optional/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/httpsonly/1.0.2/sync.yaml b/artifacthub/library/general/httpsonly/1.0.2/sync.yaml new file mode 100644 index 000000000..b5f00c4dd --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/sync.yaml @@ -0,0 +1,14 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "extensions" + version: "v1beta1" + kind: "Ingress" + - group: "networking.k8s.io" + version: "v1beta1" + kind: "Ingress" diff --git a/artifacthub/library/general/httpsonly/1.0.2/template.yaml b/artifacthub/library/general/httpsonly/1.0.2/template.yaml new file mode 100644 index 000000000..5293fe72c --- /dev/null +++ b/artifacthub/library/general/httpsonly/1.0.2/template.yaml @@ -0,0 +1,71 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8shttpsonly + annotations: + metadata.gatekeeper.sh/title: "HTTPS Only" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Requires Ingress resources to be HTTPS only. Ingress resources must + include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. + By default a valid TLS {} configuration is required, this can be made + optional by setting the `tlsOptional` parameter to `true`. + + https://kubernetes.io/docs/concepts/services-networking/ingress/#tls +spec: + crd: + spec: + names: + kind: K8sHttpsOnly + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Requires Ingress resources to be HTTPS only. Ingress resources must + include the `kubernetes.io/ingress.allow-http` annotation, set to + `false`. By default a valid TLS {} configuration is required, this + can be made optional by setting the `tlsOptional` parameter to + `true`. + properties: + tlsOptional: + type: boolean + description: "When set to `true` the TLS {} is optional, defaults + to false." + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8shttpsonly + + violation[{"msg": msg}] { + input.review.object.kind == "Ingress" + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + ingress := input.review.object + not https_complete(ingress) + not tls_is_optional + msg := sprintf("Ingress should be https. tls configuration and allow-http=false annotation are required for %v", [ingress.metadata.name]) + } + + violation[{"msg": msg}] { + input.review.object.kind == "Ingress" + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + ingress := input.review.object + not annotation_complete(ingress) + tls_is_optional + msg := sprintf("Ingress should be https. The allow-http=false annotation is required for %v", [ingress.metadata.name]) + } + + https_complete(ingress) = true { + ingress.spec["tls"] + count(ingress.spec.tls) > 0 + ingress.metadata.annotations["kubernetes.io/ingress.allow-http"] == "false" + } + + annotation_complete(ingress) = true { + ingress.metadata.annotations["kubernetes.io/ingress.allow-http"] == "false" + } + + tls_is_optional { + parameters := object.get(input, "parameters", {}) + object.get(parameters, "tlsOptional", false) == true + } diff --git a/artifacthub/library/general/imagedigests/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/imagedigests/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..b7d77075b --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.1 +name: k8simagedigests +displayName: Image Digests +createdAt: "2023-10-30T21:00:00Z" +description: |- + Requires container images to contain a digest. + https://kubernetes.io/docs/concepts/containers/images/ +digest: ef359e8377bf69afbe0e7e7cbc48549baa6974f22aa98d88de4417c5b455ef18 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/imagedigests +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Image Digests + Requires container images to contain a digest. + https://kubernetes.io/docs/concepts/containers/images/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/imagedigests/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/imagedigests/1.0.1/kustomization.yaml b/artifacthub/library/general/imagedigests/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/constraint.yaml b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/constraint.yaml new file mode 100644 index 000000000..e1cae7cdf --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/constraint.yaml @@ -0,0 +1,11 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sImageDigests +metadata: + name: container-image-must-have-digest +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + namespaces: + - "default" diff --git a/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/disallowed_all.yaml b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/disallowed_all.yaml new file mode 100644 index 000000000..b576d4301 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/disallowed_all.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed +spec: + initContainers: + - name: opainit + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_allowed.yaml b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_allowed.yaml new file mode 100644 index 000000000..81b3fea48 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2@sha256:04ff8fce2afd1a3bc26260348e5b290e8d945b1fad4b4c16d22834c2f3a1814a + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_disallowed.yaml b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_disallowed.yaml new file mode 100644 index 000000000..a19eef5c6 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/samples/container-image-must-have-digest/example_disallowed.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed +spec: + initContainers: + - name: opainit + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" diff --git a/artifacthub/library/general/imagedigests/1.0.1/suite.yaml b/artifacthub/library/general/imagedigests/1.0.1/suite.yaml new file mode 100644 index 000000000..3e853c8f6 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/suite.yaml @@ -0,0 +1,31 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: imagedigests +tests: +- name: container-image-must-have-digest + template: template.yaml + constraint: samples/container-image-must-have-digest/constraint.yaml + cases: + - name: example-allowed + object: samples/container-image-must-have-digest/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/container-image-must-have-digest/example_disallowed.yaml + assertions: + - violations: 2 + - message: initContainer + violations: 1 + - message: container + violations: 1 + - name: disallowed-all + object: samples/container-image-must-have-digest/disallowed_all.yaml + assertions: + - violations: 3 + - message: initContainer + violations: 1 + - message: container + violations: 1 + - message: ephemeralContainer + violations: 1 diff --git a/artifacthub/library/general/imagedigests/1.0.1/template.yaml b/artifacthub/library/general/imagedigests/1.0.1/template.yaml new file mode 100644 index 000000000..e00a4b608 --- /dev/null +++ b/artifacthub/library/general/imagedigests/1.0.1/template.yaml @@ -0,0 +1,82 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8simagedigests + annotations: + metadata.gatekeeper.sh/title: "Image Digests" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires container images to contain a digest. + + https://kubernetes.io/docs/concepts/containers/images/ +spec: + crd: + spec: + names: + kind: K8sImageDigests + validation: + openAPIV3Schema: + type: object + description: >- + Requires container images to contain a digest. + + https://kubernetes.io/docs/concepts/containers/images/ + properties: + exemptImages: + description: >- + Any container that uses an image that matches an entry in this list will be excluded + from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`. + + It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name) + in order to avoid unexpectedly exempting images from an untrusted repository. + type: array + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8simagedigests + + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg}] { + container := input.review.object.spec.containers[_] + not is_exempt(container) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) + msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image]) + } + + violation[{"msg": msg}] { + container := input.review.object.spec.initContainers[_] + not is_exempt(container) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) + msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) + } + + violation[{"msg": msg}] { + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) + msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) + } + libs: + - | + 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/artifacthub/library/general/noupdateserviceaccount/1.0.1/README.md b/artifacthub/library/general/noupdateserviceaccount/1.0.1/README.md new file mode 100644 index 000000000..4843dc5dc --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/README.md @@ -0,0 +1,13 @@ +# NoUpdateServiceAccount + +**NOTE:** This policy is ignored in `audit` mode, because it only blocks +updates to existing resources, not specific configurations. + +The `NoUpdateServiceAccount` constraint blocks updating the service account on +resources that abstract over Pods. + +This policy helps prevent workloads with "update-self" permissions from +escalating further in the cluster by selecting a new service account to +run as. It is especially useful for workloads running in sensitive +namespaces like `kube-system`, where nearby service accounts are likely to +have cluster admin rights. diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..25f517ecc --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: noupdateserviceaccount +displayName: Block updating Service Account +createdAt: "2023-10-30T21:00:00Z" +description: Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode. +digest: ebe8c51d51643cc8d55a2f315f19326db6c81c1fba9c0e0bfb9914b657a67203 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/noupdateserviceaccount +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Block updating Service Account + Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/noupdateserviceaccount/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/kustomization.yaml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/constraint.yaml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/constraint.yaml new file mode 100644 index 000000000..d8920759e --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/constraint.yaml @@ -0,0 +1,33 @@ +# IMPORTANT: Before deploying this policy, make sure you allow-list any groups +# or users that need to deploy workloads to kube-system, such as cluster- +# lifecycle controllers, addon managers, etc. Such controllers may need to +# update service account names during automated rollouts (e.g. of refactored +# configurations). You can allow-list them with the allowedGroups and +# allowedUsers properties of the NoUpdateServiceAccount Constraint. +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: NoUpdateServiceAccount +metadata: + name: no-update-kube-system-service-account +spec: + match: + namespaces: ["kube-system"] + kinds: + - apiGroups: [""] + kinds: + # You can optionally add "Pod" here, but it is unnecessary because + # Pod service account immutability is enforced by the Kubernetes API. + - "ReplicationController" + - apiGroups: ["apps"] + kinds: + - "ReplicaSet" + - "Deployment" + - "StatefulSet" + - "DaemonSet" + - apiGroups: ["batch"] + kinds: + # You can optionally add "Job" here, but it is unnecessary because + # Job service account immutability is enforced by the Kubernetes API. + - "CronJob" + parameters: + allowedGroups: [] + allowedUsers: [] diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/example_allowed.yaml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/example_allowed.yaml new file mode 100644 index 000000000..c6bbde27b --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/samples/noupdateserviceaccount/example_allowed.yaml @@ -0,0 +1,31 @@ +# Note: The gator tests currently require exactly one object per example file. +# Since this is an update-triggered policy, at least two objects are technically +# required to demonstrate it. Due to the gator requirement, we only have one +# object below. The policy should allow changing everything but the +# serviceAccountName field. +kind: Deployment +apiVersion: apps/v1 +metadata: + name: policy-test + namespace: kube-system + labels: + app: policy-test +spec: + replicas: 1 + selector: + matchLabels: + app: policy-test-deploy + template: + metadata: + labels: + app: policy-test-deploy + spec: + # Changing anything except this field should be allowed by the policy. + serviceAccountName: policy-test-sa-1 + containers: + - name: policy-test + image: ubuntu + command: + - /bin/bash + - -c + - sleep 99999 diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/suite.yaml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/suite.yaml new file mode 100644 index 000000000..8d4a0ec03 --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/suite.yaml @@ -0,0 +1,20 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: noupdateserviceaccount +tests: + - name: noupdateserviceaccount + template: template.yaml + constraint: samples/noupdateserviceaccount/constraint.yaml + cases: + - name: example-allowed + object: samples/noupdateserviceaccount/example_allowed.yaml + assertions: + - violations: no + # Since the tests are currently stateless, they can't exercise level-triggered + # events like changing a field. For now, manually test example_disallowed.yaml + # instead. + # - name: example-disallowed + # object: samples/noupdateserviceaccount/example_disallowed.yaml + # assertions: + # - violations: yes diff --git a/artifacthub/library/general/noupdateserviceaccount/1.0.1/template.yaml b/artifacthub/library/general/noupdateserviceaccount/1.0.1/template.yaml new file mode 100644 index 000000000..782a0d313 --- /dev/null +++ b/artifacthub/library/general/noupdateserviceaccount/1.0.1/template.yaml @@ -0,0 +1,106 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: noupdateserviceaccount + annotations: + metadata.gatekeeper.sh/title: "Block updating Service Account" + metadata.gatekeeper.sh/version: 1.0.1 + description: "Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode." +spec: + crd: + spec: + names: + kind: NoUpdateServiceAccount + validation: + openAPIV3Schema: + type: object + properties: + allowedGroups: + description: Groups that should be allowed to bypass the policy. + type: array + items: + type: string + allowedUsers: + description: Users that should be allowed to bypass the policy. + type: array + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package noupdateserviceaccount + + privileged(userInfo, allowedUsers, _) { + # Allow if the user is in allowedUsers. + # Use object.get so omitted parameters can't cause policy bypass by + # evaluating to undefined. + username := object.get(userInfo, "username", "") + allowedUsers[_] == username + } + + privileged(userInfo, _, allowedGroups) { + # Allow if the user's groups intersect allowedGroups. + # Use object.get so omitted parameters can't cause policy bypass by + # evaluating to undefined. + userGroups := object.get(userInfo, "groups", []) + groups := {g | g := userGroups[_]} + allowed := {g | g := allowedGroups[_]} + intersection := groups & allowed + count(intersection) > 0 + } + + get_service_account(obj) = spec { + obj.kind == "Pod" + spec := obj.spec.serviceAccountName + } { + obj.kind == "ReplicationController" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "ReplicaSet" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "Deployment" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "StatefulSet" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "DaemonSet" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "Job" + spec := obj.spec.template.spec.serviceAccountName + } { + obj.kind == "CronJob" + spec := obj.spec.jobTemplate.spec.template.spec.serviceAccountName + } + + violation[{"msg": msg}] { + # This policy only applies to updates of existing resources. + input.review.operation == "UPDATE" + + # Use object.get so omitted parameters can't cause policy bypass by + # evaluating to undefined. + params := object.get(input, "parameters", {}) + allowedUsers := object.get(params, "allowedUsers", []) + allowedGroups := object.get(params, "allowedGroups", []) + + # Extract the service account. + oldKSA := get_service_account(input.review.oldObject) + newKSA := get_service_account(input.review.object) + + # Deny unprivileged users and groups from changing serviceAccountName. + not privileged(input.review.userInfo, allowedUsers, allowedGroups) + oldKSA != newKSA + msg := "user does not have permission to modify serviceAccountName" + } { + # Defensively require object to have a serviceAccountName. + input.review.operation == "UPDATE" + not get_service_account(input.review.object) + msg := "missing serviceAccountName field in object under review" + } { + # Defensively require oldObject to have a serviceAccountName. + input.review.operation == "UPDATE" + not get_service_account(input.review.oldObject) + msg := "missing serviceAccountName field in oldObject under review" + } diff --git a/artifacthub/library/general/replicalimits/1.0.2/artifacthub-pkg.yml b/artifacthub/library/general/replicalimits/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..3b46cf798 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8sreplicalimits +displayName: Replica Limits +createdAt: "2023-10-30T21:00:00Z" +description: Requires that objects with the field `spec.replicas` (Deployments, ReplicaSets, etc.) specify a number of replicas within defined ranges. +digest: 858bf59f6c7408f2fb390a181b2f6db5e4d8fbe5eb580aa45b5601d6ae2d4064 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/replicalimits +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Replica Limits + Requires that objects with the field `spec.replicas` (Deployments, ReplicaSets, etc.) specify a number of replicas within defined ranges. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/replicalimits/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/replicalimits/1.0.2/kustomization.yaml b/artifacthub/library/general/replicalimits/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/constraint.yaml b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/constraint.yaml new file mode 100644 index 000000000..b496235f3 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sReplicaLimits +metadata: + name: replica-limits +spec: + match: + kinds: + - apiGroups: ["apps"] + kinds: ["Deployment"] + parameters: + ranges: + - min_replicas: 3 + max_replicas: 50 diff --git a/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_allowed.yaml b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_allowed.yaml new file mode 100644 index 000000000..f5a2b1d8c --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_allowed.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: allowed-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 3 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_disallowed.yaml b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_disallowed.yaml new file mode 100644 index 000000000..1c4899d20 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/samples/replicalimits/example_disallowed.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: disallowed-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 100 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/replicalimits/1.0.2/suite.yaml b/artifacthub/library/general/replicalimits/1.0.2/suite.yaml new file mode 100644 index 000000000..598efb814 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/suite.yaml @@ -0,0 +1,17 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: replicalimits +tests: +- name: replica-limit + template: template.yaml + constraint: samples/replicalimits/constraint.yaml + cases: + - name: example-allowed + object: samples/replicalimits/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/replicalimits/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/replicalimits/1.0.2/template.yaml b/artifacthub/library/general/replicalimits/1.0.2/template.yaml new file mode 100644 index 000000000..2e44fb2c1 --- /dev/null +++ b/artifacthub/library/general/replicalimits/1.0.2/template.yaml @@ -0,0 +1,58 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8sreplicalimits + annotations: + metadata.gatekeeper.sh/title: "Replica Limits" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Requires that objects with the field `spec.replicas` (Deployments, + ReplicaSets, etc.) specify a number of replicas within defined ranges. +spec: + crd: + spec: + names: + kind: K8sReplicaLimits + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + properties: + ranges: + type: array + description: Allowed ranges for numbers of replicas. Values are inclusive. + items: + type: object + description: A range of allowed replicas. Values are inclusive. + properties: + min_replicas: + description: The minimum number of replicas allowed, inclusive. + type: integer + max_replicas: + description: The maximum number of replicas allowed, inclusive. + type: integer + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8sreplicalimits + + object_name = input.review.object.metadata.name + object_kind = input.review.kind.kind + + violation[{"msg": msg}] { + spec := input.review.object.spec + not input_replica_limit(spec) + msg := sprintf("The provided number of replicas is not allowed for %v: %v. Allowed ranges: %v", [object_kind, object_name, input.parameters]) + } + + input_replica_limit(spec) { + provided := spec.replicas + count(input.parameters.ranges) > 0 + range := input.parameters.ranges[_] + value_within_range(range, provided) + } + + value_within_range(range, value) { + range.min_replicas <= value + range.max_replicas >= value + } diff --git a/artifacthub/library/general/requiredannotations/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/requiredannotations/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..424fe5cc1 --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: k8srequiredannotations +displayName: Required Annotations +createdAt: "2023-10-30T21:00:00Z" +description: Requires resources to contain specified annotations, with values matching provided regular expressions. +digest: 332839ec5e037ea20aa5b9a204ad2490ad76d05f5d2b961ace5e90c7b8c864be +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/requiredannotations +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Required Annotations + Requires resources to contain specified annotations, with values matching provided regular expressions. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/requiredannotations/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/requiredannotations/1.0.1/kustomization.yaml b/artifacthub/library/general/requiredannotations/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/constraint.yaml b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/constraint.yaml new file mode 100644 index 000000000..033700136 --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/constraint.yaml @@ -0,0 +1,18 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sRequiredAnnotations +metadata: + name: all-must-have-certain-set-of-annotations +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Service"] + parameters: + message: "All services must have a `a8r.io/owner` and `a8r.io/runbook` annotations." + annotations: + - key: a8r.io/owner + # Matches email address or github user + allowedRegex: ^([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}|[a-z]{1,39})$ + - key: a8r.io/runbook + # Matches urls including or not http/https + allowedRegex: ^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$ diff --git a/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_allowed.yaml b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_allowed.yaml new file mode 100644 index 000000000..b3b9f95ad --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_allowed.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: allowed-service + annotations: + a8r.io/owner: "dev-team-alfa@contoso.com" + a8r.io/runbook: "https://confluence.contoso.com/dev-team-alfa/runbooks" +spec: + ports: + - name: http + port: 80 + targetPort: 8080 + selector: + app: foo diff --git a/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_disallowed.yaml b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_disallowed.yaml new file mode 100644 index 000000000..62c01b877 --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/samples/all-must-have-certain-set-of-annotations/example_disallowed.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: disallowed-service +spec: + ports: + - name: http + port: 80 + targetPort: 8080 + selector: + app: foo diff --git a/artifacthub/library/general/requiredannotations/1.0.1/suite.yaml b/artifacthub/library/general/requiredannotations/1.0.1/suite.yaml new file mode 100644 index 000000000..48bf7303a --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/suite.yaml @@ -0,0 +1,17 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: requiredannotations +tests: +- name: must-have-set-of-annotations + template: template.yaml + constraint: samples/all-must-have-certain-set-of-annotations/constraint.yaml + cases: + - name: example-allowed + object: samples/all-must-have-certain-set-of-annotations/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/all-must-have-certain-set-of-annotations/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/requiredannotations/1.0.1/template.yaml b/artifacthub/library/general/requiredannotations/1.0.1/template.yaml new file mode 100644 index 000000000..634acb181 --- /dev/null +++ b/artifacthub/library/general/requiredannotations/1.0.1/template.yaml @@ -0,0 +1,59 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8srequiredannotations + annotations: + metadata.gatekeeper.sh/title: "Required Annotations" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires resources to contain specified annotations, with values matching + provided regular expressions. +spec: + crd: + spec: + names: + kind: K8sRequiredAnnotations + validation: + openAPIV3Schema: + type: object + properties: + message: + type: string + annotations: + type: array + description: >- + A list of annotations and values the object must specify. + items: + type: object + properties: + key: + type: string + description: >- + The required annotation. + allowedRegex: + type: string + description: >- + If specified, a regular expression the annotation's value + must match. The value must contain at least one match for + the regular expression. + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8srequiredannotations + + violation[{"msg": msg, "details": {"missing_annotations": missing}}] { + provided := {annotation | input.review.object.metadata.annotations[annotation]} + required := {annotation | annotation := input.parameters.annotations[_].key} + missing := required - provided + count(missing) > 0 + msg := sprintf("you must provide annotation(s): %v", [missing]) + } + + violation[{"msg": msg}] { + value := input.review.object.metadata.annotations[key] + expected := input.parameters.annotations[_] + expected.key == key + expected.allowedRegex != "" + not regex.match(expected.allowedRegex, value) + msg := sprintf("Annotation <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) + } diff --git a/artifacthub/library/general/requiredlabels/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/requiredlabels/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..c8a953a27 --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: k8srequiredlabels +displayName: Required Labels +createdAt: "2023-10-30T21:00:00Z" +description: Requires resources to contain specified labels, with values matching provided regular expressions. +digest: aa4cbb2bbaba13b310108f7944ba8200c0adbaf865f8f3dfd7cbdc3c760b5eea +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/requiredlabels +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Required Labels + Requires resources to contain specified labels, with values matching provided regular expressions. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/requiredlabels/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/requiredlabels/1.0.1/kustomization.yaml b/artifacthub/library/general/requiredlabels/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/constraint.yaml b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/constraint.yaml new file mode 100644 index 000000000..806e9862f --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/constraint.yaml @@ -0,0 +1,14 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sRequiredLabels +metadata: + name: all-must-have-owner +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Namespace"] + parameters: + message: "All namespaces must have an `owner` label that points to your company username" + labels: + - key: owner + allowedRegex: "^[a-zA-Z]+.agilebank.demo$" diff --git a/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_allowed.yaml b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_allowed.yaml new file mode 100644 index 000000000..e2d3b9c03 --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_allowed.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: allowed-namespace + labels: + owner: user.agilebank.demo diff --git a/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_disallowed.yaml b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_disallowed.yaml new file mode 100644 index 000000000..a7a53610a --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/samples/all-must-have-owner/example_disallowed.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: disallowed-namespace diff --git a/artifacthub/library/general/requiredlabels/1.0.1/suite.yaml b/artifacthub/library/general/requiredlabels/1.0.1/suite.yaml new file mode 100644 index 000000000..64c5b4130 --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/suite.yaml @@ -0,0 +1,17 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: requiredlabels +tests: +- name: must-have-owner + template: template.yaml + constraint: samples/all-must-have-owner/constraint.yaml + cases: + - name: example-allowed + object: samples/all-must-have-owner/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/all-must-have-owner/example_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/requiredlabels/1.0.1/template.yaml b/artifacthub/library/general/requiredlabels/1.0.1/template.yaml new file mode 100644 index 000000000..aa865394c --- /dev/null +++ b/artifacthub/library/general/requiredlabels/1.0.1/template.yaml @@ -0,0 +1,68 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8srequiredlabels + annotations: + metadata.gatekeeper.sh/title: "Required Labels" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Requires resources to contain specified labels, with values matching + provided regular expressions. +spec: + crd: + spec: + names: + kind: K8sRequiredLabels + validation: + openAPIV3Schema: + type: object + properties: + message: + type: string + labels: + type: array + description: >- + A list of labels and values the object must specify. + items: + type: object + properties: + key: + type: string + description: >- + The required label. + allowedRegex: + type: string + description: >- + If specified, a regular expression the annotation's value + must match. The value must contain at least one match for + the regular expression. + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8srequiredlabels + + get_message(parameters, _default) := _default { + not parameters.message + } + + get_message(parameters, _) := parameters.message + + violation[{"msg": msg, "details": {"missing_labels": missing}}] { + provided := {label | input.review.object.metadata.labels[label]} + required := {label | label := input.parameters.labels[_].key} + missing := required - provided + count(missing) > 0 + def_msg := sprintf("you must provide labels: %v", [missing]) + msg := get_message(input.parameters, def_msg) + } + + violation[{"msg": msg}] { + value := input.review.object.metadata.labels[key] + expected := input.parameters.labels[_] + expected.key == key + # do not match if allowedRegex is not defined, or is an empty string + expected.allowedRegex != "" + not regex.match(expected.allowedRegex, value) + def_msg := sprintf("Label <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) + msg := get_message(input.parameters, def_msg) + } diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/artifacthub-pkg.yml b/artifacthub/library/general/uniqueingresshost/1.0.4/artifacthub-pkg.yml new file mode 100644 index 000000000..595927481 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.4 +name: k8suniqueingresshost +displayName: Unique Ingress Host +createdAt: "2023-10-30T21:00:00Z" +description: |- + Requires all Ingress rule hosts to be unique. + Does not handle hostname wildcards: https://kubernetes.io/docs/concepts/services-networking/ingress/ +digest: 8c335b1ae3f5d162beea4b6f747c632a871c98ea62b762ac4ae4d90259cdfb5d +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/uniqueingresshost +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Unique Ingress Host + Requires all Ingress rule hosts to be unique. + Does not handle hostname wildcards: https://kubernetes.io/docs/concepts/services-networking/ingress/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/uniqueingresshost/1.0.4/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/kustomization.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/constraint.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/constraint.yaml new file mode 100644 index 000000000..b4d7f852f --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/constraint.yaml @@ -0,0 +1,9 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sUniqueIngressHost +metadata: + name: unique-ingress-host +spec: + match: + kinds: + - apiGroups: ["extensions", "networking.k8s.io"] + kinds: ["Ingress"] diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_allowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_allowed.yaml new file mode 100644 index 000000000..1e819e200 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_allowed.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-allowed + namespace: default +spec: + rules: + - host: example-allowed-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 + - host: example-allowed-host1.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx2 + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed.yaml new file mode 100644 index 000000000..c61893ed6 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-disallowed + namespace: default +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed2.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed2.yaml new file mode 100644 index 000000000..1ca131f13 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_disallowed2.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-disallowed2 + namespace: default +spec: + rules: + - host: example-host2.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 + - host: example-host3.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx2 + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed.yaml new file mode 100644 index 000000000..06bc70922 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-example + namespace: default +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed2.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed2.yaml new file mode 100644 index 000000000..3f826aeeb --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/samples/unique-ingress-host/example_inventory_disallowed2.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-example2 + namespace: default +spec: + rules: + - host: example-host2.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/suite.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/suite.yaml new file mode 100644 index 000000000..630838d1d --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: uniqueingresshost +tests: +- name: unique-ingress-host + template: template.yaml + constraint: samples/unique-ingress-host/constraint.yaml + cases: + - name: example-allowed + object: samples/unique-ingress-host/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/unique-ingress-host/example_disallowed.yaml + inventory: + - samples/unique-ingress-host/example_inventory_disallowed.yaml + assertions: + - violations: yes + - name: example-disallowed2 + object: samples/unique-ingress-host/example_disallowed2.yaml + inventory: + - samples/unique-ingress-host/example_inventory_disallowed2.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/sync.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/sync.yaml new file mode 100644 index 000000000..ce25235ac --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/sync.yaml @@ -0,0 +1,17 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "extensions" + version: "v1beta1" + kind: "Ingress" + - group: "networking.k8s.io" + version: "v1beta1" + kind: "Ingress" + - group: "networking.k8s.io" + version: "v1" + kind: "Ingress" diff --git a/artifacthub/library/general/uniqueingresshost/1.0.4/template.yaml b/artifacthub/library/general/uniqueingresshost/1.0.4/template.yaml new file mode 100644 index 000000000..c534b2a20 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.4/template.yaml @@ -0,0 +1,52 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8suniqueingresshost + annotations: + metadata.gatekeeper.sh/title: "Unique Ingress Host" + metadata.gatekeeper.sh/version: 1.0.4 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups": ["extensions"], + "versions": ["v1beta1"], + "kinds": ["Ingress"] + }, + { + "groups": ["networking.k8s.io"], + "versions": ["v1beta1", "v1"], + "kinds": ["Ingress"] + } + ] + ]" + description: >- + Requires all Ingress rule hosts to be unique. + + Does not handle hostname wildcards: + https://kubernetes.io/docs/concepts/services-networking/ingress/ +spec: + crd: + spec: + names: + kind: K8sUniqueIngressHost + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8suniqueingresshost + + identical(obj, review) { + obj.metadata.namespace == review.object.metadata.namespace + obj.metadata.name == review.object.metadata.name + } + + violation[{"msg": msg}] { + input.review.kind.kind == "Ingress" + regex.match("^(extensions|networking.k8s.io)$", input.review.kind.group) + host := input.review.object.spec.rules[_].host + other := data.inventory.namespace[_][otherapiversion]["Ingress"][name] + regex.match("^(extensions|networking.k8s.io)/.+$", otherapiversion) + other.spec.rules[_].host == host + not identical(other, input.review) + msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host]) + } diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..681ac0400 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spspcapabilities +displayName: Capabilities +createdAt: "2023-10-30T21:00:01Z" +description: Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities +digest: 6a8f1f152f379ac8ca91ad35c9d0da66bdabd1d9f61c62cf15310b7f1a37de1d +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/capabilities +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Capabilities + Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/capabilities/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/constraint.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/constraint.yaml new file mode 100644 index 000000000..3f856082f --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/constraint.yaml @@ -0,0 +1,14 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPCapabilities +metadata: + name: capabilities-demo +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + namespaces: + - "default" + parameters: + allowedCapabilities: ["something"] + requiredDropCapabilities: ["must_drop"] diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/disallowed_ephemeral.yaml new file mode 100644 index 000000000..5467c826e --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/disallowed_ephemeral.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + ephemeralContainers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + securityContext: + capabilities: + add: ["disallowedcapability"] + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_allowed.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_allowed.yaml new file mode 100644 index 000000000..41bf6a0ed --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_allowed.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-allowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + securityContext: + capabilities: + add: ["something"] + drop: ["must_drop", "another_one"] + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_disallowed.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_disallowed.yaml new file mode 100644 index 000000000..fdd886189 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/example_disallowed.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo +spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + securityContext: + capabilities: + add: ["disallowedcapability"] + resources: + limits: + cpu: "100m" + memory: "30Mi" \ No newline at end of file diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/update.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/update.yaml new file mode 100644 index 000000000..df8ea0070 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/samples/capabilities-demo/update.yaml @@ -0,0 +1,26 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: opa-disallowed + labels: + owner: me.agilebank.demo + spec: + containers: + - name: opa + image: openpolicyagent/opa:0.9.2 + args: + - "run" + - "--server" + - "--addr=localhost:8080" + securityContext: + capabilities: + add: ["disallowedcapability"] + resources: + limits: + cpu: "100m" + memory: "30Mi" diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/suite.yaml new file mode 100644 index 000000000..48c2fcb46 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: capabilities +tests: + - name: capabilities + template: template.yaml + constraint: samples/capabilities-demo/constraint.yaml + cases: + - name: example-disallowed + object: samples/capabilities-demo/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/capabilities-demo/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/capabilities-demo/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/capabilities-demo/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/capabilities/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/capabilities/1.0.2/template.yaml new file mode 100644 index 000000000..2501a1538 --- /dev/null +++ b/artifacthub/library/pod-security-policy/capabilities/1.0.2/template.yaml @@ -0,0 +1,160 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspcapabilities + annotations: + metadata.gatekeeper.sh/title: "Capabilities" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Controls Linux capabilities on containers. Corresponds to the + `allowedCapabilities` and `requiredDropCapabilities` fields in a + PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities +spec: + crd: + spec: + names: + kind: K8sPSPCapabilities + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls Linux capabilities on containers. Corresponds to the + `allowedCapabilities` and `requiredDropCapabilities` fields in a + PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities + 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 + allowedCapabilities: + type: array + description: "A list of Linux capabilities that can be added to a container." + items: + type: string + requiredDropCapabilities: + type: array + description: "A list of Linux capabilities that are required to be dropped from a container." + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package capabilities + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg}] { + # spec.containers.securityContext.capabilities field is immutable. + not is_update(input.review) + + container := input.review.object.spec.containers[_] + not is_exempt(container) + has_disallowed_capabilities(container) + msg := sprintf("container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) + } + + violation[{"msg": msg}] { + not is_update(input.review) + container := input.review.object.spec.containers[_] + not is_exempt(container) + missing_drop_capabilities(container) + msg := sprintf("container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) + } + + + + violation[{"msg": msg}] { + not is_update(input.review) + container := input.review.object.spec.initContainers[_] + not is_exempt(container) + has_disallowed_capabilities(container) + msg := sprintf("init container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) + } + + violation[{"msg": msg}] { + not is_update(input.review) + container := input.review.object.spec.initContainers[_] + not is_exempt(container) + missing_drop_capabilities(container) + msg := sprintf("init container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) + } + + + + violation[{"msg": msg}] { + not is_update(input.review) + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + has_disallowed_capabilities(container) + msg := sprintf("ephemeral container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) + } + + violation[{"msg": msg}] { + not is_update(input.review) + container := input.review.object.spec.ephemeralContainers[_] + not is_exempt(container) + missing_drop_capabilities(container) + msg := sprintf("ephemeral container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) + } + + + has_disallowed_capabilities(container) { + allowed := {c | c := lower(input.parameters.allowedCapabilities[_])} + not allowed["*"] + capabilities := {c | c := lower(container.securityContext.capabilities.add[_])} + + count(capabilities - allowed) > 0 + } + + missing_drop_capabilities(container) { + must_drop := {c | c := lower(input.parameters.requiredDropCapabilities[_])} + all := {"all"} + dropped := {c | c := lower(container.securityContext.capabilities.drop[_])} + + count(must_drop - dropped) > 0 + count(all - dropped) > 0 + } + + get_default(obj, param, _) := obj[param] + + get_default(obj, param, _default) := _default { + not obj[param] + not obj[param] == false + } + 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/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/README.md b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/README.md new file mode 100644 index 000000000..d8a40937d --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/README.md @@ -0,0 +1,36 @@ +# Forbidden Sysctls security context policy + +The forbidden sysctls constraint allows one to limit the set of kernel parameters that can be modified by pods. This is accomplished by specifying a combination of allowed and forbidden sysctls using either of two parameters: `allowedSysctls` and `forbiddenSysctls`. + +## Parameters + +`allowedSysctls`: A list of explicitly allowed sysctls. Any sysctl not in this list will be considered forbidden. '*' and trailing wildcards are supported. If unspecified, no limitations are made by this parameter. + +`forbiddenSysctls`: A list of explicitly denied sysctls. Any sysctl in this list will be considered forbidden. '*' and trailing wildcards are supported. If unspecified, no limitations are made by this parameter. + +## Examples + +```yaml +parameters: + allowedSysctls: ['*'] + forbiddenSysctls: + - kernel.msg* + - net.core.somaxconn +``` + +```yaml +parameters: + allowedSysctls: + - kernel.shm_rmid_forced + - net.ipv4.ip_local_port_range + - net.ipv4.tcp_syncookies + - net.ipv4.ping_group_range + forbiddenSysctls: [] +``` + +*Note*: `forbiddenSysctls` takes precedence, such that an explicitly forbidden sysctl is still forbidden even if it appears in `allowedSysctls` as well. However in practice, such overlap between the rules should be avoided. + +## References + +* [Using sysctls in a Kubernetes Cluster](https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/) +* [Kubernetes API Reference - Sysctl](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#sysctl-v1-core) \ No newline at end of file diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/artifacthub-pkg.yml new file mode 100644 index 000000000..21402ceae --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.1.3 +name: k8spspforbiddensysctls +displayName: Forbidden Sysctls +createdAt: "2023-10-30T21:00:01Z" +description: Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ +digest: 97bcd0da74c88e9c8c8e55738081253a0fb45e0289b76f17cbe5d5632d751d6f +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/forbidden-sysctls +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Forbidden Sysctls + Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/kustomization.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/constraint.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/constraint.yaml new file mode 100644 index 000000000..39abf4b23 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/constraint.yaml @@ -0,0 +1,15 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPForbiddenSysctls +metadata: + name: psp-forbidden-sysctls +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + forbiddenSysctls: + # - "*" # * may be used to forbid all sysctls + - kernel.* + allowedSysctls: + - "*" # allows all sysctls. allowedSysctls is optional. diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_allowed.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_allowed.yaml new file mode 100644 index 000000000..4b6cc4b66 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_allowed.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-forbidden-sysctls-disallowed + labels: + app: nginx-forbidden-sysctls +spec: + containers: + - name: nginx + image: nginx + securityContext: + sysctls: + - name: net.core.somaxconn + value: "1024" diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_disallowed.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_disallowed.yaml new file mode 100644 index 000000000..34ab8f344 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/example_disallowed.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-forbidden-sysctls-disallowed + labels: + app: nginx-forbidden-sysctls +spec: + containers: + - name: nginx + image: nginx + securityContext: + sysctls: + - name: kernel.msgmax + value: "65536" + - name: net.core.somaxconn + value: "1024" diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/update.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/update.yaml new file mode 100644 index 000000000..e4e732be9 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/samples/psp-forbidden-sysctls/update.yaml @@ -0,0 +1,21 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-forbidden-sysctls-disallowed + labels: + app: nginx-forbidden-sysctls + spec: + containers: + - name: nginx + image: nginx + securityContext: + sysctls: + - name: kernel.msgmax + value: "65536" + - name: net.core.somaxconn + value: "1024" diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/suite.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/suite.yaml new file mode 100644 index 000000000..d00f85b8b --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/suite.yaml @@ -0,0 +1,21 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: forbidden-sysctls +tests: + - name: forbidden-sysctls + template: template.yaml + constraint: samples/psp-forbidden-sysctls/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-forbidden-sysctls/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-forbidden-sysctls/example_allowed.yaml + assertions: + - violations: no + - name: update + object: samples/psp-forbidden-sysctls/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/template.yaml b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/template.yaml new file mode 100644 index 000000000..053c0eae5 --- /dev/null +++ b/artifacthub/library/pod-security-policy/forbidden-sysctls/1.1.3/template.yaml @@ -0,0 +1,100 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspforbiddensysctls + annotations: + metadata.gatekeeper.sh/title: "Forbidden Sysctls" + metadata.gatekeeper.sh/version: 1.1.3 + description: >- + Controls the `sysctl` profile used by containers. Corresponds to the + `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. + When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. + The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. + For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ +spec: + crd: + spec: + names: + kind: K8sPSPForbiddenSysctls + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls the `sysctl` profile used by containers. Corresponds to the + `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. + When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. + The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. + For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ + properties: + allowedSysctls: + type: array + description: "An allow-list of sysctls. `*` allows all sysctls not listed in the `forbiddenSysctls` parameter." + items: + type: string + forbiddenSysctls: + type: array + description: "A disallow-list of sysctls. `*` forbids all sysctls." + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspforbiddensysctls + + import data.lib.exclude_update.is_update + + # Block if forbidden + violation[{"msg": msg, "details": {}}] { + # spec.securityContext.sysctls field is immutable. + not is_update(input.review) + + sysctl := input.review.object.spec.securityContext.sysctls[_].name + forbidden_sysctl(sysctl) + msg := sprintf("The sysctl %v is not allowed, pod: %v. Forbidden sysctls: %v", [sysctl, input.review.object.metadata.name, input.parameters.forbiddenSysctls]) + } + + # Block if not explicitly allowed + violation[{"msg": msg, "details": {}}] { + not is_update(input.review) + sysctl := input.review.object.spec.securityContext.sysctls[_].name + not allowed_sysctl(sysctl) + msg := sprintf("The sysctl %v is not explicitly allowed, pod: %v. Allowed sysctls: %v", [sysctl, input.review.object.metadata.name, input.parameters.allowedSysctls]) + } + + # * may be used to forbid all sysctls + forbidden_sysctl(_) { + input.parameters.forbiddenSysctls[_] == "*" + } + + forbidden_sysctl(sysctl) { + input.parameters.forbiddenSysctls[_] == sysctl + } + + forbidden_sysctl(sysctl) { + forbidden := input.parameters.forbiddenSysctls[_] + endswith(forbidden, "*") + startswith(sysctl, trim_suffix(forbidden, "*")) + } + + # * may be used to allow all sysctls + allowed_sysctl(_) { + input.parameters.allowedSysctls[_] == "*" + } + + allowed_sysctl(sysctl) { + input.parameters.allowedSysctls[_] == sysctl + } + + allowed_sysctl(sysctl) { + allowed := input.parameters.allowedSysctls[_] + endswith(allowed, "*") + startswith(sysctl, trim_suffix(allowed, "*")) + } + libs: + - | + package lib.exclude_update + + is_update(review) { + review.operation == "UPDATE" + } diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/README.md b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/README.md new file mode 100644 index 000000000..b70d94d45 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/README.md @@ -0,0 +1,7 @@ +# Deprecated + +**This Policy is deprecated** + +Please use the FSGroup settings on the users policy to enforce FSGroup Settings. + +[Users Policy](../users) diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..de11f20c9 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spspfsgroup +displayName: FS Group +createdAt: "2023-10-30T21:00:01Z" +description: Controls allocating an FSGroup that owns the Pod's volumes. Corresponds to the `fsGroup` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +digest: fbccd31e516f56b1a82fdd979614e110862a2434c89171398eb95db0d468f50b +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/fsgroup +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # FS Group + Controls allocating an FSGroup that owns the Pod's volumes. Corresponds to the `fsGroup` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/fsgroup/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/constraint.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/constraint.yaml new file mode 100644 index 000000000..4eb14fe3c --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/constraint.yaml @@ -0,0 +1,14 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPFSGroup +metadata: + name: psp-fsgroup +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + rule: "MayRunAs" #"MustRunAs" #"MayRunAs", "RunAsAny" + ranges: + - min: 1 + max: 1000 diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_allowed.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_allowed.yaml new file mode 100644 index 000000000..17d3274c3 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_allowed.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: fsgroup-disallowed +spec: + securityContext: + fsGroup: 500 # directory will have group ID 500 + volumes: + - name: fsgroup-demo-vol + emptyDir: {} + containers: + - name: fsgroup-demo + image: busybox + command: ["sh", "-c", "sleep 1h"] + volumeMounts: + - name: fsgroup-demo-vol + mountPath: /data/demo diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_disallowed.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_disallowed.yaml new file mode 100644 index 000000000..9caf7c0a3 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/example_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: fsgroup-disallowed +spec: + securityContext: + fsGroup: 2000 # directory will have group ID 2000 + volumes: + - name: fsgroup-demo-vol + emptyDir: {} + containers: + - name: fsgroup-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + volumeMounts: + - name: fsgroup-demo-vol + mountPath: /data/demo diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/update.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/update.yaml new file mode 100644 index 000000000..c0de7258a --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/samples/psp-fsgroup/update.yaml @@ -0,0 +1,22 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: fsgroup-disallowed + spec: + securityContext: + fsGroup: 2000 # directory will have group ID 2000 + volumes: + - name: fsgroup-demo-vol + emptyDir: {} + containers: + - name: fsgroup-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + volumeMounts: + - name: fsgroup-demo-vol + mountPath: /data/demo diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/suite.yaml new file mode 100644 index 000000000..cb102e785 --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/suite.yaml @@ -0,0 +1,21 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: fsgroup +tests: + - name: fsgroup + template: template.yaml + constraint: samples/psp-fsgroup/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-fsgroup/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-fsgroup/example_allowed.yaml + assertions: + - violations: no + - name: update + object: samples/psp-fsgroup/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/fsgroup/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/template.yaml new file mode 100644 index 000000000..4e1b9449a --- /dev/null +++ b/artifacthub/library/pod-security-policy/fsgroup/1.0.2/template.yaml @@ -0,0 +1,105 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspfsgroup + annotations: + metadata.gatekeeper.sh/title: "FS Group" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Controls allocating an FSGroup that owns the Pod's volumes. Corresponds + to the `fsGroup` field in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +spec: + crd: + spec: + names: + kind: K8sPSPFSGroup + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls allocating an FSGroup that owns the Pod's volumes. Corresponds + to the `fsGroup` field in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + properties: + rule: + description: "An FSGroup rule name." + enum: + - MayRunAs + - MustRunAs + - RunAsAny + type: string + ranges: + type: array + description: "GID ranges affected by the rule." + items: + type: object + properties: + min: + description: "The minimum GID in the range, inclusive." + type: integer + max: + description: "The maximum GID in the range, inclusive." + type: integer + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspfsgroup + + import data.lib.exclude_update.is_update + + violation[{"msg": msg, "details": {}}] { + # spec.securityContext.fsGroup field is immutable. + not is_update(input.review) + + spec := input.review.object.spec + not input_fsGroup_allowed(spec) + msg := sprintf("The provided pod spec fsGroup is not allowed, pod: %v. Allowed fsGroup: %v", [input.review.object.metadata.name, input.parameters]) + } + + input_fsGroup_allowed(_) { + # RunAsAny - No range is required. Allows any fsGroup ID to be specified. + input.parameters.rule == "RunAsAny" + } + input_fsGroup_allowed(spec) { + # MustRunAs - Validates pod spec fsgroup against all ranges + input.parameters.rule == "MustRunAs" + fg := spec.securityContext.fsGroup + count(input.parameters.ranges) > 0 + range := input.parameters.ranges[_] + value_within_range(range, fg) + } + input_fsGroup_allowed(spec) { + # MayRunAs - Validates pod spec fsgroup against all ranges or allow pod spec fsgroup to be left unset + input.parameters.rule == "MayRunAs" + not has_field(spec, "securityContext") + } + input_fsGroup_allowed(spec) { + # MayRunAs - Validates pod spec fsgroup against all ranges or allow pod spec fsgroup to be left unset + input.parameters.rule == "MayRunAs" + not spec.securityContext.fsGroup + } + input_fsGroup_allowed(spec) { + # MayRunAs - Validates pod spec fsgroup against all ranges or allow pod spec fsgroup to be left unset + input.parameters.rule == "MayRunAs" + fg := spec.securityContext.fsGroup + count(input.parameters.ranges) > 0 + range := input.parameters.ranges[_] + value_within_range(range, fg) + } + value_within_range(range, value) { + range.min <= value + range.max >= value + } + # has_field returns whether an object has a field + has_field(object, field) = true { + object[field] + } + libs: + - | + package lib.exclude_update + + is_update(review) { + review.operation == "UPDATE" + } diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..714090b4f --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spsphostfilesystem +displayName: Host Filesystem +createdAt: "2023-10-30T21:00:01Z" +description: Controls usage of the host filesystem. Corresponds to the `allowedHostPaths` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +digest: 48def0bbdca86b91c2d545e4b155793a69dc202192d8547f69d6d2b84e41a319 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/host-filesystem +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Host Filesystem + Controls usage of the host filesystem. Corresponds to the `allowedHostPaths` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/constraint.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/constraint.yaml new file mode 100644 index 000000000..7cbd7b824 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPHostFilesystem +metadata: + name: psp-host-filesystem +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + allowedHostPaths: + - readOnly: true + pathPrefix: "/foo" diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/disallowed_ephemeral.yaml new file mode 100644 index 000000000..beece55c0 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/disallowed_ephemeral.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-filesystem + labels: + app: nginx-host-filesystem-disallowed +spec: + ephemeralContainers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + readOnly: true + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_allowed.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_allowed.yaml new file mode 100644 index 000000000..abc60d882 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_allowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-filesystem + labels: + app: nginx-host-filesystem-disallowed +spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + readOnly: true + volumes: + - name: cache-volume + hostPath: + path: /foo/bar diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_disallowed.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_disallowed.yaml new file mode 100644 index 000000000..53107694f --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/example_disallowed.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-filesystem + labels: + app: nginx-host-filesystem-disallowed +spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + readOnly: true + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/update.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/update.yaml new file mode 100644 index 000000000..68b28a536 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/samples/psp-host-filesystem/update.yaml @@ -0,0 +1,23 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-host-filesystem + labels: + app: nginx-host-filesystem-disallowed + spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + readOnly: true + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/suite.yaml new file mode 100644 index 000000000..5441df8cc --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: host-filesystem +tests: + - name: host-filesystem + template: template.yaml + constraint: samples/psp-host-filesystem/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-host-filesystem/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-host-filesystem/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-host-filesystem/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/psp-host-filesystem/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/template.yaml new file mode 100644 index 000000000..5f506c351 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-filesystem/1.0.2/template.yaml @@ -0,0 +1,148 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spsphostfilesystem + annotations: + metadata.gatekeeper.sh/title: "Host Filesystem" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Controls usage of the host filesystem. Corresponds to the + `allowedHostPaths` field in a PodSecurityPolicy. For more information, + see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +spec: + crd: + spec: + names: + kind: K8sPSPHostFilesystem + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls usage of the host filesystem. Corresponds to the + `allowedHostPaths` field in a PodSecurityPolicy. For more information, + see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + properties: + allowedHostPaths: + type: array + description: "An array of hostpath objects, representing paths and read/write configuration." + items: + type: object + properties: + pathPrefix: + type: string + description: "The path prefix that the host volume must match." + readOnly: + type: boolean + description: "when set to true, any container volumeMounts matching the pathPrefix must include `readOnly: true`." + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spsphostfilesystem + + import data.lib.exclude_update.is_update + + violation[{"msg": msg, "details": {}}] { + # spec.volumes field is immutable. + not is_update(input.review) + + volume := input_hostpath_volumes[_] + allowedPaths := get_allowed_paths(input) + input_hostpath_violation(allowedPaths, volume) + msg := sprintf("HostPath volume %v is not allowed, pod: %v. Allowed path: %v", [volume, input.review.object.metadata.name, allowedPaths]) + } + + input_hostpath_violation(allowedPaths, _) { + # An empty list means all host paths are blocked + allowedPaths == [] + } + input_hostpath_violation(allowedPaths, volume) { + not input_hostpath_allowed(allowedPaths, volume) + } + + get_allowed_paths(arg) = out { + not arg.parameters + out = [] + } + get_allowed_paths(arg) = out { + not arg.parameters.allowedHostPaths + out = [] + } + get_allowed_paths(arg) = out { + out = arg.parameters.allowedHostPaths + } + + input_hostpath_allowed(allowedPaths, volume) { + allowedHostPath := allowedPaths[_] + path_matches(allowedHostPath.pathPrefix, volume.hostPath.path) + not allowedHostPath.readOnly == true + } + + input_hostpath_allowed(allowedPaths, volume) { + allowedHostPath := allowedPaths[_] + path_matches(allowedHostPath.pathPrefix, volume.hostPath.path) + allowedHostPath.readOnly + not writeable_input_volume_mounts(volume.name) + } + + writeable_input_volume_mounts(volume_name) { + container := input_containers[_] + mount := container.volumeMounts[_] + mount.name == volume_name + not mount.readOnly + } + + # This allows "/foo", "/foo/", "/foo/bar" etc., but + # disallows "/fool", "/etc/foo" etc. + path_matches(prefix, path) { + a := path_array(prefix) + b := path_array(path) + prefix_matches(a, b) + } + path_array(p) = out { + p != "/" + out := split(trim(p, "/"), "/") + } + # This handles the special case for "/", since + # split(trim("/", "/"), "/") == [""] + path_array("/") = [] + + prefix_matches(a, b) { + count(a) <= count(b) + not any_not_equal_upto(a, b, count(a)) + } + + any_not_equal_upto(a, b, n) { + a[i] != b[i] + i < n + } + + input_hostpath_volumes[v] { + v := input.review.object.spec.volumes[_] + has_field(v, "hostPath") + } + + # has_field returns whether an object has a field + has_field(object, field) = true { + object[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" + } diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..54ebdc968 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spsphostnetworkingports +displayName: Host Networking Ports +createdAt: "2023-10-30T21:00:01Z" +description: Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and `hostPorts` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces +digest: ae7dce558b0f89d28d03646ba8b2f5fdbfe179bc2d4f082d544042d798fcff4b +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/host-network-ports +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Host Networking Ports + Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and `hostPorts` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/constraint.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/constraint.yaml new file mode 100644 index 000000000..fcbc5d805 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPHostNetworkingPorts +metadata: + name: psp-host-network-ports +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + hostNetwork: true + min: 80 + max: 9000 diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/disallowed_ephemeral.yaml new file mode 100644 index 000000000..7a4fa3114 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/disallowed_ephemeral.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-networking-ports-disallowed + labels: + app: nginx-host-networking-ports +spec: + hostNetwork: true + ephemeralContainers: + - name: nginx + image: nginx + ports: + - containerPort: 9001 + hostPort: 9001 diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_allowed.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_allowed.yaml new file mode 100644 index 000000000..08b321fe5 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_allowed.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-networking-ports-allowed + labels: + app: nginx-host-networking-ports +spec: + hostNetwork: false + containers: + - name: nginx + image: nginx + ports: + - containerPort: 9000 + hostPort: 80 diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_disallowed.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_disallowed.yaml new file mode 100644 index 000000000..9a496cd60 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/example_disallowed.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-host-networking-ports-disallowed + labels: + app: nginx-host-networking-ports +spec: + hostNetwork: true + containers: + - name: nginx + image: nginx + ports: + - containerPort: 9001 + hostPort: 9001 diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/update.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/update.yaml new file mode 100644 index 000000000..231096430 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/samples/psp-host-network-ports/update.yaml @@ -0,0 +1,19 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-host-networking-ports-disallowed + labels: + app: nginx-host-networking-ports + spec: + hostNetwork: true + containers: + - name: nginx + image: nginx + ports: + - containerPort: 9001 + hostPort: 9001 diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/suite.yaml new file mode 100644 index 000000000..710df69eb --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: host-network-ports +tests: +- name: use-of-host-networking-ports-blocked + template: template.yaml + constraint: samples/psp-host-network-ports/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-host-network-ports/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-host-network-ports/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-host-network-ports/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/psp-host-network-ports/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/template.yaml new file mode 100644 index 000000000..0f04aae03 --- /dev/null +++ b/artifacthub/library/pod-security-policy/host-network-ports/1.0.2/template.yaml @@ -0,0 +1,118 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spsphostnetworkingports + annotations: + metadata.gatekeeper.sh/title: "Host Networking Ports" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Controls usage of host network namespace by pod containers. Specific + ports must be specified. Corresponds to the `hostNetwork` and + `hostPorts` fields in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces +spec: + crd: + spec: + names: + kind: K8sPSPHostNetworkingPorts + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls usage of host network namespace by pod containers. Specific + ports must be specified. Corresponds to the `hostNetwork` and + `hostPorts` fields in a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces + 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 + hostNetwork: + description: "Determines if the policy allows the use of HostNetwork in the pod spec." + type: boolean + min: + description: "The start of the allowed port range, inclusive." + type: integer + max: + description: "The end of the allowed port range, inclusive." + type: integer + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spsphostnetworkingports + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg, "details": {}}] { + # spec.hostNetwork field is immutable. + not is_update(input.review) + + input_share_hostnetwork(input.review.object) + msg := sprintf("The specified hostNetwork and hostPort are not allowed, pod: %v. Allowed values: %v", [input.review.object.metadata.name, input.parameters]) + } + + input_share_hostnetwork(o) { + not input.parameters.hostNetwork + o.spec.hostNetwork + } + + input_share_hostnetwork(_) { + hostPort := input_containers[_].ports[_].hostPort + hostPort < input.parameters.min + } + + input_share_hostnetwork(_) { + hostPort := input_containers[_].ports[_].hostPort + hostPort > input.parameters.max + } + + input_containers[c] { + c := input.review.object.spec.containers[_] + not is_exempt(c) + } + + input_containers[c] { + c := input.review.object.spec.initContainers[_] + not is_exempt(c) + } + + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + not is_exempt(c) + } + 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/artifacthub/library/pod-security-policy/proc-mount/1.0.3/README.md b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/README.md new file mode 100644 index 000000000..9e45b7207 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/README.md @@ -0,0 +1,12 @@ +# ProcMount security context policy + +`procMount` denotes the type of proc mount to use for the containers. The default is `DefaultProcMount` which uses the container runtime defaults for readonly paths and masked paths. + +Types of proc mount are: + +- `DefaultProcMount` uses the container runtime default ProcType. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information. + +- `UnmaskedProcMount` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications. + +This requires the `ProcMountType` feature flag to be enabled. Set `--feature-gates=ProcMountType=true` in Kubernetes API Server to be able to use `Unmasked` procMount type (requires v1.12 and above). For more information, see +https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options and https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/. diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/artifacthub-pkg.yml new file mode 100644 index 000000000..cd2ef8855 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.3 +name: k8spspprocmount +displayName: Proc Mount +createdAt: "2023-10-30T21:00:01Z" +description: Controls the allowed `procMount` types for the container. Corresponds to the `allowedProcMountTypes` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#allowedprocmounttypes +digest: f143a4f9759f7ee3e2b987948a74df1b534b55e5b30c6304aef417647cb04aef +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/proc-mount +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Proc Mount + Controls the allowed `procMount` types for the container. Corresponds to the `allowedProcMountTypes` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#allowedprocmounttypes +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/proc-mount/1.0.3/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/kustomization.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/constraint.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/constraint.yaml new file mode 100644 index 000000000..1d7434ac0 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/constraint.yaml @@ -0,0 +1,11 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPProcMount +metadata: + name: psp-proc-mount +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + procMount: Default diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/disallowed_ephemeral.yaml new file mode 100644 index 000000000..4be38f45d --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-proc-mount-disallowed + labels: + app: nginx-proc-mount +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + procMount: Unmasked #Default diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_allowed.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_allowed.yaml new file mode 100644 index 000000000..c9b13ac71 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-proc-mount-disallowed + labels: + app: nginx-proc-mount +spec: + containers: + - name: nginx + image: nginx + securityContext: + procMount: Default diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_disallowed.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_disallowed.yaml new file mode 100644 index 000000000..403c7cb2a --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/example_disallowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-proc-mount-disallowed + labels: + app: nginx-proc-mount +spec: + containers: + - name: nginx + image: nginx + securityContext: + procMount: Unmasked #Default diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/update.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/update.yaml new file mode 100644 index 000000000..dc21b1142 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/samples/psp-proc-mount/update.yaml @@ -0,0 +1,17 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-proc-mount-disallowed + labels: + app: nginx-proc-mount + spec: + containers: + - name: nginx + image: nginx + securityContext: + procMount: Unmasked #Default diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/suite.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/suite.yaml new file mode 100644 index 000000000..501493e14 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: proc-mount +tests: +- name: default-proc-mount-required + template: template.yaml + constraint: samples/psp-proc-mount/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-proc-mount/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-proc-mount/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-proc-mount/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/psp-proc-mount/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/proc-mount/1.0.3/template.yaml b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/template.yaml new file mode 100644 index 000000000..5fb816793 --- /dev/null +++ b/artifacthub/library/pod-security-policy/proc-mount/1.0.3/template.yaml @@ -0,0 +1,138 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspprocmount + annotations: + metadata.gatekeeper.sh/title: "Proc Mount" + metadata.gatekeeper.sh/version: 1.0.3 + description: >- + Controls the allowed `procMount` types for the container. Corresponds to + the `allowedProcMountTypes` field in a PodSecurityPolicy. For more + information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#allowedprocmounttypes +spec: + crd: + spec: + names: + kind: K8sPSPProcMount + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls the allowed `procMount` types for the container. Corresponds to + the `allowedProcMountTypes` field in a PodSecurityPolicy. For more + information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#allowedprocmounttypes + 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 + procMount: + type: string + description: >- + Defines the strategy for the security exposure of certain paths + in `/proc` by the container runtime. Setting to `Default` uses + the runtime defaults, where `Unmasked` bypasses the default + behavior. + enum: + - Default + - Unmasked + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspprocmount + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + violation[{"msg": msg, "details": {}}] { + # spec.containers.securityContext.procMount field is immutable. + not is_update(input.review) + + c := input_containers[_] + not is_exempt(c) + allowedProcMount := get_allowed_proc_mount(input) + not input_proc_mount_type_allowed(allowedProcMount, c) + msg := sprintf("ProcMount type is not allowed, container: %v. Allowed procMount types: %v", [c.name, allowedProcMount]) + } + + input_proc_mount_type_allowed(allowedProcMount, c) { + allowedProcMount == "default" + lower(c.securityContext.procMount) == "default" + } + input_proc_mount_type_allowed(allowedProcMount, _) { + allowedProcMount == "unmasked" + } + + input_containers[c] { + c := input.review.object.spec.containers[_] + c.securityContext.procMount + } + input_containers[c] { + c := input.review.object.spec.initContainers[_] + c.securityContext.procMount + } + input_containers[c] { + c := input.review.object.spec.ephemeralContainers[_] + c.securityContext.procMount + } + + get_allowed_proc_mount(arg) = out { + not arg.parameters + out = "default" + } + get_allowed_proc_mount(arg) = out { + not arg.parameters.procMount + out = "default" + } + get_allowed_proc_mount(arg) = out { + arg.parameters.procMount + not valid_proc_mount(arg.parameters.procMount) + out = "default" + } + get_allowed_proc_mount(arg) = out { + valid_proc_mount(arg.parameters.procMount) + out = lower(arg.parameters.procMount) + } + + valid_proc_mount(str) { + lower(str) == "default" + } + valid_proc_mount(str) { + lower(str) == "unmasked" + } + 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/artifacthub/library/pod-security-policy/seccomp/1.0.1/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..8b14fcfcb --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: k8spspseccomp +displayName: Seccomp +createdAt: "2023-10-30T21:00:02Z" +description: Controls the seccomp profile used by containers. Corresponds to the `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp +digest: cfa37037755930c6c076fd04a0124baa5b0918548ecccd51b1fa3a3365d5c8a1 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/seccomp +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Seccomp + Controls the seccomp profile used by containers. Corresponds to the `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/seccomp/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/kustomization.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/constraint.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/constraint.yaml new file mode 100644 index 000000000..d26af154e --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPSeccomp +metadata: + name: psp-seccomp +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + allowedProfiles: + - runtime/default + - docker/default diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/disallowed_ephemeral.yaml new file mode 100644 index 000000000..1555d700e --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/disallowed_ephemeral.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-disallowed + annotations: + container.seccomp.security.alpha.kubernetes.io/nginx: unconfined + labels: + app: nginx-seccomp +spec: + ephemeralContainers: + - name: nginx + image: nginx diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed.yaml new file mode 100644 index 000000000..2ff43d307 --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-allowed + annotations: + container.seccomp.security.alpha.kubernetes.io/nginx: runtime/default + labels: + app: nginx-seccomp +spec: + containers: + - name: nginx + image: nginx diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed2.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed2.yaml new file mode 100644 index 000000000..f8766e774 --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_allowed2.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-allowed2 + annotations: + seccomp.security.alpha.kubernetes.io/pod: runtime/default + labels: + app: nginx-seccomp +spec: + containers: + - name: nginx + image: nginx diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed.yaml new file mode 100644 index 000000000..8e94ca7e6 --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-disallowed + annotations: + container.seccomp.security.alpha.kubernetes.io/nginx: unconfined + labels: + app: nginx-seccomp +spec: + containers: + - name: nginx + image: nginx diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed2.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed2.yaml new file mode 100644 index 000000000..6008d8f72 --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/samples/psp-seccomp/example_disallowed2.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-seccomp-disallowed2 + annotations: + seccomp.security.alpha.kubernetes.io/pod: unconfined + labels: + app: nginx-seccomp +spec: + containers: + - name: nginx + image: nginx diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/suite.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/suite.yaml new file mode 100644 index 000000000..62336b26e --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/suite.yaml @@ -0,0 +1,32 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: seccomp +tests: +- name: default-seccomp-required + template: template.yaml + constraint: samples/psp-seccomp/constraint.yaml + cases: + - name: example-disallowed-global + object: samples/psp-seccomp/example_disallowed2.yaml + assertions: + - violations: 1 + message: "Seccomp profile 'unconfined' is not allowed for container 'nginx'. Found at: annotation seccomp.security.alpha.kubernetes.io/pod" + - name: example-disallowed-container + object: samples/psp-seccomp/example_disallowed.yaml + assertions: + - violations: 1 + message: "Seccomp profile 'unconfined' is not allowed for container 'nginx'. Found at: annotation container.seccomp.security.alpha.kubernetes.io/nginx" + - name: example-allowed-container + object: samples/psp-seccomp/example_allowed.yaml + assertions: + - violations: no + - name: example-allowed-global + object: samples/psp-seccomp/example_allowed2.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-seccomp/disallowed_ephemeral.yaml + assertions: + - violations: 1 + message: "Seccomp profile 'unconfined' is not allowed for container 'nginx'. Found at: annotation container.seccomp.security.alpha.kubernetes.io/nginx" diff --git a/artifacthub/library/pod-security-policy/seccomp/1.0.1/template.yaml b/artifacthub/library/pod-security-policy/seccomp/1.0.1/template.yaml new file mode 100644 index 000000000..d252a1ace --- /dev/null +++ b/artifacthub/library/pod-security-policy/seccomp/1.0.1/template.yaml @@ -0,0 +1,281 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspseccomp + annotations: + metadata.gatekeeper.sh/title: "Seccomp" + metadata.gatekeeper.sh/version: 1.0.1 + description: >- + Controls the seccomp profile used by containers. Corresponds to the + `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on + a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp +spec: + crd: + spec: + names: + kind: K8sPSPSeccomp + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Controls the seccomp profile used by containers. Corresponds to the + `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on + a PodSecurityPolicy. For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + 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 + allowedProfiles: + type: array + description: >- + An array of allowed profile values for seccomp on Pods/Containers. + + Can use the annotation naming scheme: `runtime/default`, `docker/default`, `unconfined` and/or + `localhost/some-profile.json`. The item `localhost/*` will allow any localhost based profile. + + Can also use the securityContext naming scheme: `RuntimeDefault`, `Unconfined` + and/or `Localhost`. For securityContext `Localhost`, use the parameter `allowedLocalhostProfiles` + to list the allowed profile JSON files. + + The policy code will translate between the two schemes so it is not necessary to use both. + + Putting a `*` in this array allows all Profiles to be used. + + This field is required since with an empty list this policy will block all workloads. + items: + type: string + allowedLocalhostFiles: + type: array + description: >- + When using securityContext naming scheme for seccomp and including `Localhost` this array holds + the allowed profile JSON files. + + Putting a `*` in this array will allows all JSON files to be used. + + This field is required to allow `Localhost` in securityContext as with an empty list it will block. + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspseccomp + + import data.lib.exempt_container.is_exempt + + container_annotation_key_prefix = "container.seccomp.security.alpha.kubernetes.io/" + + pod_annotation_key = "seccomp.security.alpha.kubernetes.io/pod" + + naming_translation = { + # securityContext -> annotation + "RuntimeDefault": ["runtime/default", "docker/default"], + "Unconfined": ["unconfined"], + "Localhost": ["localhost"], + # annotation -> securityContext + "runtime/default": ["RuntimeDefault"], + "docker/default": ["RuntimeDefault"], + "unconfined": ["Unconfined"], + "localhost": ["Localhost"], + } + + violation[{"msg": msg}] { + not input_wildcard_allowed_profiles + allowed_profiles := get_allowed_profiles + container := input_containers[name] + not is_exempt(container) + result := get_profile(container) + not allowed_profile(result.profile, result.file, allowed_profiles) + msg := get_message(result.profile, result.file, name, result.location, allowed_profiles) + } + + get_message(profile, _, name, location, allowed_profiles) = message { + not profile == "Localhost" + message := sprintf("Seccomp profile '%v' is not allowed for container '%v'. Found at: %v. Allowed profiles: %v", [profile, name, location, allowed_profiles]) + } + + get_message(profile, file, name, location, allowed_profiles) = message { + profile == "Localhost" + message := sprintf("Seccomp profile '%v' with file '%v' is not allowed for container '%v'. Found at: %v. Allowed profiles: %v", [profile, file, name, location, allowed_profiles]) + } + + input_wildcard_allowed_profiles { + input.parameters.allowedProfiles[_] == "*" + } + + input_wildcard_allowed_files { + input.parameters.allowedLocalhostFiles[_] == "*" + } + + input_wildcard_allowed_files { + "localhost/*" == input.parameters.allowedProfiles[_] + } + + # Simple allowed Profiles + allowed_profile(profile, _, allowed) { + not startswith(lower(profile), "localhost") + profile == allowed[_] + } + + # seccomp Localhost without wildcard + allowed_profile(profile, file, allowed) { + profile == "Localhost" + not input_wildcard_allowed_files + profile == allowed[_] + allowed_files := {x | x := object.get(input.parameters, "allowedLocalhostFiles", [])[_]} | get_annotation_localhost_files + file == allowed_files[_] + } + + # seccomp Localhost with wildcard + allowed_profile(profile, _, allowed) { + profile == "Localhost" + input_wildcard_allowed_files + profile == allowed[_] + } + + # annotation localhost with wildcard + allowed_profile(profile, _, allowed) { + "localhost/*" == allowed[_] + startswith(profile, "localhost/") + } + + # annotation localhost without wildcard + allowed_profile(profile, _, allowed) { + startswith(profile, "localhost/") + profile == allowed[_] + } + + # Localhost files from annotation scheme + get_annotation_localhost_files[file] { + profile := input.parameters.allowedProfiles[_] + startswith(profile, "localhost/") + file := replace(profile, "localhost/", "") + } + + # The profiles explicitly in the list + get_allowed_profiles[allowed] { + allowed := input.parameters.allowedProfiles[_] + } + + # The simply translated profiles + get_allowed_profiles[allowed] { + profile := input.parameters.allowedProfiles[_] + not startswith(lower(profile), "localhost") + allowed := naming_translation[profile][_] + } + + # Seccomp Localhost to annotation translation + get_allowed_profiles[allowed] { + profile := input.parameters.allowedProfiles[_] + profile == "Localhost" + file := object.get(input.parameters, "allowedLocalhostFiles", [])[_] + allowed := sprintf("%v/%v", [naming_translation[profile][_], file]) + } + + # Annotation localhost to Seccomp translation + get_allowed_profiles[allowed] { + profile := input.parameters.allowedProfiles[_] + startswith(profile, "localhost") + allowed := naming_translation.localhost[_] + } + + # Container profile as defined in pod annotation + get_profile(container) = {"profile": profile, "file": "", "location": location} { + not has_securitycontext_container(container) + not has_annotation(get_container_annotation_key(container.name)) + not has_securitycontext_pod + profile := input.review.object.metadata.annotations[pod_annotation_key] + location := sprintf("annotation %v", [pod_annotation_key]) + } + + # Container profile as defined in container annotation + get_profile(container) = {"profile": profile, "file": "", "location": location} { + not has_securitycontext_container(container) + not has_securitycontext_pod + container_annotation := get_container_annotation_key(container.name) + has_annotation(container_annotation) + profile := input.review.object.metadata.annotations[container_annotation] + location := sprintf("annotation %v", [container_annotation]) + } + + # Container profile as defined in pods securityContext + get_profile(container) = {"profile": profile, "file": file, "location": location} { + not has_securitycontext_container(container) + profile := input.review.object.spec.securityContext.seccompProfile.type + file := object.get(input.review.object.spec.securityContext.seccompProfile, "localhostProfile", "") + location := "pod securityContext" + } + + # Container profile as defined in containers securityContext + get_profile(container) = {"profile": profile, "file": file, "location": location} { + has_securitycontext_container(container) + profile := container.securityContext.seccompProfile.type + file := object.get(container.securityContext.seccompProfile, "localhostProfile", "") + location := "container securityContext" + } + + # Container profile missing + get_profile(container) = {"profile": "not configured", "file": "", "location": "no explicit profile found"} { + not has_annotation(get_container_annotation_key(container.name)) + not has_annotation(pod_annotation_key) + not has_securitycontext_pod + not has_securitycontext_container(container) + } + + has_annotation(annotation) { + input.review.object.metadata.annotations[annotation] + } + + has_securitycontext_pod { + input.review.object.spec.securityContext.seccompProfile + } + + has_securitycontext_container(container) { + container.securityContext.seccompProfile + } + + get_container_annotation_key(name) = annotation { + annotation := concat("", [container_annotation_key_prefix, name]) + } + + input_containers[container.name] = container { + container := input.review.object.spec.containers[_] + } + + input_containers[container.name] = container { + container := input.review.object.spec.initContainers[_] + } + + input_containers[container.name] = container { + container := input.review.object.spec.ephemeralContainers[_] + } + libs: + - | + package lib.exempt_container + + 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/artifacthub/library/pod-security-policy/selinux/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/selinux/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..4b7ae97a0 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spspselinuxv2 +displayName: SELinux V2 +createdAt: "2023-10-30T21:00:02Z" +description: Defines an allow-list of seLinuxOptions configurations for pod containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux +digest: a472297f77af518459c368a2bf1c38c0fe6023f492fc6796fde75ad7a4ea131f +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/selinux +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # SELinux V2 + Defines an allow-list of seLinuxOptions configurations for pod containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/selinux/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/constraint.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/constraint.yaml new file mode 100644 index 000000000..f88bbcd69 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/constraint.yaml @@ -0,0 +1,15 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPSELinuxV2 +metadata: + name: psp-selinux-v2 +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + allowedSELinuxOptions: + - level: s0:c123,c456 + role: object_r + type: svirt_sandbox_file_t + user: system_u diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/disallowed_ephemeral.yaml new file mode 100644 index 000000000..3a35fc737 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/disallowed_ephemeral.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-selinux-disallowed + labels: + app: nginx-selinux +spec: + ephemeralContainers: + - name: nginx + image: nginx + securityContext: + seLinuxOptions: + level: s1:c234,c567 + user: sysadm_u + role: sysadm_r + type: svirt_lxc_net_t diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_allowed.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_allowed.yaml new file mode 100644 index 000000000..4eaf2dc92 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_allowed.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-selinux-allowed + labels: + app: nginx-selinux +spec: + containers: + - name: nginx + image: nginx + securityContext: + seLinuxOptions: + level: s0:c123,c456 + role: object_r + type: svirt_sandbox_file_t + user: system_u diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_disallowed.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_disallowed.yaml new file mode 100644 index 000000000..7eb7fee11 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/example_disallowed.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-selinux-disallowed + labels: + app: nginx-selinux +spec: + containers: + - name: nginx + image: nginx + securityContext: + seLinuxOptions: + level: s1:c234,c567 + user: sysadm_u + role: sysadm_r + type: svirt_lxc_net_t diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/update.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/update.yaml new file mode 100644 index 000000000..581419e9d --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/samples/psp-selinux-v2/update.yaml @@ -0,0 +1,21 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-selinux-disallowed + labels: + app: nginx-selinux + spec: + containers: + - name: nginx + image: nginx + securityContext: + seLinuxOptions: + level: s1:c234,c567 + user: sysadm_u + role: sysadm_r + type: svirt_lxc_net_t diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/suite.yaml new file mode 100644 index 000000000..1bbaf360e --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: selinux +tests: +- name: require-matching-selinux-options + template: template.yaml + constraint: samples/psp-selinux-v2/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-selinux-v2/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-selinux-v2/example_allowed.yaml + assertions: + - violations: no + - name: disallowed-ephemeral + object: samples/psp-selinux-v2/disallowed_ephemeral.yaml + assertions: + - violations: yes + - name: update + object: samples/psp-selinux-v2/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/selinux/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/selinux/1.0.2/template.yaml new file mode 100644 index 000000000..a2a502b16 --- /dev/null +++ b/artifacthub/library/pod-security-policy/selinux/1.0.2/template.yaml @@ -0,0 +1,144 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspselinuxv2 + annotations: + metadata.gatekeeper.sh/title: "SELinux V2" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Defines an allow-list of seLinuxOptions configurations for pod + containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. + For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux +spec: + crd: + spec: + names: + kind: K8sPSPSELinuxV2 + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Defines an allow-list of seLinuxOptions configurations for pod + containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. + For more information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux + 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 + allowedSELinuxOptions: + type: array + description: "An allow-list of SELinux options configurations." + items: + type: object + description: "An allowed configuration of SELinux options for a pod container." + properties: + level: + type: string + description: "An SELinux level." + role: + type: string + description: "An SELinux role." + type: + type: string + description: "An SELinux type." + user: + type: string + description: "An SELinux user." + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspselinux + + import data.lib.exclude_update.is_update + import data.lib.exempt_container.is_exempt + + # Disallow top level custom SELinux options + violation[{"msg": msg, "details": {}}] { + # spec.securityContext.seLinuxOptions field is immutable. + not is_update(input.review) + + has_field(input.review.object.spec.securityContext, "seLinuxOptions") + not input_seLinuxOptions_allowed(input.review.object.spec.securityContext.seLinuxOptions) + msg := sprintf("SELinux options is not allowed, pod: %v. Allowed options: %v", [input.review.object.metadata.name, input.parameters.allowedSELinuxOptions]) + } + # Disallow container level custom SELinux options + violation[{"msg": msg, "details": {}}] { + # spec.containers.securityContext.seLinuxOptions field is immutable. + not is_update(input.review) + + c := input_security_context[_] + not is_exempt(c) + has_field(c.securityContext, "seLinuxOptions") + not input_seLinuxOptions_allowed(c.securityContext.seLinuxOptions) + msg := sprintf("SELinux options is not allowed, pod: %v, container %v. Allowed options: %v", [input.review.object.metadata.name, c.name, input.parameters.allowedSELinuxOptions]) + } + + input_seLinuxOptions_allowed(options) { + params := input.parameters.allowedSELinuxOptions[_] + field_allowed("level", options, params) + field_allowed("role", options, params) + field_allowed("type", options, params) + field_allowed("user", options, params) + } + + field_allowed(field, options, params) { + params[field] == options[field] + } + field_allowed(field, options, _) { + not has_field(options, field) + } + + input_security_context[c] { + c := input.review.object.spec.containers[_] + has_field(c.securityContext, "seLinuxOptions") + } + input_security_context[c] { + c := input.review.object.spec.initContainers[_] + has_field(c.securityContext, "seLinuxOptions") + } + input_security_context[c] { + c := input.review.object.spec.ephemeralContainers[_] + has_field(c.securityContext, "seLinuxOptions") + } + + # has_field returns whether an object has a field + has_field(object, field) = true { + object[field] + } + libs: + - | + package lib.exclude_update + + is_update(review) { + review.operation == "UPDATE" + } + - | + package lib.exempt_container + + is_exempt(container) { + exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", []) + img := container.image + exemption := exempt_images[_] + _matches_exemption(img, exemption) + } + + _matches_exemption(img, exemption) { + not endswith(exemption, "*") + exemption == img + } + + _matches_exemption(img, exemption) { + endswith(exemption, "*") + prefix := trim_suffix(exemption, "*") + startswith(img, prefix) + } diff --git a/artifacthub/library/pod-security-policy/users/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/users/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..5cfa65e70 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spspallowedusers +displayName: Allowed Users +createdAt: "2023-10-30T21:00:02Z" +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: 485bfc85639175c748da7632863dd3c91ad7f4dbd2544d2579cb82732ee795ea +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.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/users/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/constraint.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/samples/psp-pods-allowed-user-ranges/constraint.yaml new file mode 100644 index 000000000..e69974578 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.0.2/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: MustRunAs # 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.0.2/samples/psp-pods-allowed-user-ranges/disallowed_ephemeral.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/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.0.2/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.0.2/samples/psp-pods-allowed-user-ranges/example_allowed.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/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.0.2/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.0.2/samples/psp-pods-allowed-user-ranges/example_disallowed.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/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.0.2/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.0.2/samples/psp-pods-allowed-user-ranges/update.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/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.0.2/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.0.2/suite.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/suite.yaml new file mode 100644 index 000000000..5c6e49640 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.0.2/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.0.2/template.yaml b/artifacthub/library/pod-security-policy/users/1.0.2/template.yaml new file mode 100644 index 000000000..613fc9307 --- /dev/null +++ b/artifacthub/library/pod-security-policy/users/1.0.2/template.yaml @@ -0,0 +1,289 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspallowedusers + annotations: + metadata.gatekeeper.sh/title: "Allowed Users" + metadata.gatekeeper.sh/version: 1.0.2 + 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 + 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/artifacthub/library/pod-security-policy/volumes/1.0.2/artifacthub-pkg.yml b/artifacthub/library/pod-security-policy/volumes/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..39688ea1a --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.2 +name: k8spspvolumetypes +displayName: Volume Types +createdAt: "2023-10-30T21:00:02Z" +description: Restricts mountable volume types to those specified by the user. Corresponds to the `volumes` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +digest: e94d48090afb1d63dc8fdf84ffaa64e650a14d02244bbc9099eeab73d89ec5c6 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/volumes +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Volume Types + Restricts mountable volume types to those specified by the user. Corresponds to the `volumes` field in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/volumes/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/kustomization.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/constraint.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/constraint.yaml new file mode 100644 index 000000000..0638df7cb --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/constraint.yaml @@ -0,0 +1,20 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPSPVolumeTypes +metadata: + name: psp-volume-types +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["Pod"] + parameters: + volumes: + # - "*" # * may be used to allow all volume types + - configMap + - emptyDir + - projected + - secret + - downwardAPI + - persistentVolumeClaim + #- hostPath #required for allowedHostPaths + - flexVolume #required for allowedFlexVolumes diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_allowed.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_allowed.yaml new file mode 100644 index 000000000..df6251e7d --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_allowed.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-volume-types-allowed + labels: + app: nginx-volume-types +spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + - name: nginx2 + image: nginx + volumeMounts: + - mountPath: /cache2 + name: demo-vol + volumes: + - name: cache-volume + emptyDir: {} + - name: demo-vol + emptyDir: {} diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_disallowed.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_disallowed.yaml new file mode 100644 index 000000000..562cf59d8 --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/example_disallowed.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-volume-types-disallowed + labels: + app: nginx-volume-types +spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + - name: nginx2 + image: nginx + volumeMounts: + - mountPath: /cache2 + name: demo-vol + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host + - name: demo-vol + emptyDir: {} diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/update.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/update.yaml new file mode 100644 index 000000000..f25f07267 --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/samples/psp-volume-types/update.yaml @@ -0,0 +1,29 @@ +kind: AdmissionReview +apiVersion: admission.k8s.io/v1beta1 +request: + operation: "UPDATE" + object: + apiVersion: v1 + kind: Pod + metadata: + name: nginx-volume-types-disallowed + labels: + app: nginx-volume-types + spec: + containers: + - name: nginx + image: nginx + volumeMounts: + - mountPath: /cache + name: cache-volume + - name: nginx2 + image: nginx + volumeMounts: + - mountPath: /cache2 + name: demo-vol + volumes: + - name: cache-volume + hostPath: + path: /tmp # directory location on host + - name: demo-vol + emptyDir: {} diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/suite.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/suite.yaml new file mode 100644 index 000000000..083aad6eb --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/suite.yaml @@ -0,0 +1,21 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: volumes +tests: +- name: host-path-disallowed + template: template.yaml + constraint: samples/psp-volume-types/constraint.yaml + cases: + - name: example-disallowed + object: samples/psp-volume-types/example_disallowed.yaml + assertions: + - violations: yes + - name: example-allowed + object: samples/psp-volume-types/example_allowed.yaml + assertions: + - violations: no + - name: update + object: samples/psp-volume-types/update.yaml + assertions: + - violations: no diff --git a/artifacthub/library/pod-security-policy/volumes/1.0.2/template.yaml b/artifacthub/library/pod-security-policy/volumes/1.0.2/template.yaml new file mode 100644 index 000000000..74165c8f4 --- /dev/null +++ b/artifacthub/library/pod-security-policy/volumes/1.0.2/template.yaml @@ -0,0 +1,64 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spspvolumetypes + annotations: + metadata.gatekeeper.sh/title: "Volume Types" + metadata.gatekeeper.sh/version: 1.0.2 + description: >- + Restricts mountable volume types to those specified by the user. + Corresponds to the `volumes` field in a PodSecurityPolicy. For more + information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems +spec: + crd: + spec: + names: + kind: K8sPSPVolumeTypes + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + description: >- + Restricts mountable volume types to those specified by the user. + Corresponds to the `volumes` field in a PodSecurityPolicy. For more + information, see + https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + properties: + volumes: + description: "`volumes` is an array of volume types. All volume types can be enabled using `*`." + type: array + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spspvolumetypes + + import data.lib.exclude_update.is_update + + violation[{"msg": msg, "details": {}}] { + # spec.volumes field is immutable. + not is_update(input.review) + + volume_fields := {x | input.review.object.spec.volumes[_][x]; x != "name"} + field := volume_fields[_] + not input_volume_type_allowed(field) + msg := sprintf("The volume type %v is not allowed, pod: %v. Allowed volume types: %v", [field, input.review.object.metadata.name, input.parameters.volumes]) + } + + # * may be used to allow all volume types + input_volume_type_allowed(_) { + input.parameters.volumes[_] == "*" + } + + input_volume_type_allowed(field) { + field == input.parameters.volumes[_] + } + libs: + - | + package lib.exclude_update + + is_update(review) { + review.operation == "UPDATE" + } diff --git a/library/general/allowedrepos/template.yaml b/library/general/allowedrepos/template.yaml index 23ad89603..3c554d8e7 100644 --- a/library/general/allowedrepos/template.yaml +++ b/library/general/allowedrepos/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8sallowedrepos annotations: metadata.gatekeeper.sh/title: "Allowed Repositories" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to begin with a string from the specified list. spec: @@ -29,21 +29,18 @@ spec: violation[{"msg": msg}] { container := input.review.object.spec.containers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } diff --git a/library/general/containerlimits/template.yaml b/library/general/containerlimits/template.yaml index 8e6867240..4b254c663 100644 --- a/library/general/containerlimits/template.yaml +++ b/library/general/containerlimits/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8scontainerlimits annotations: metadata.gatekeeper.sh/title: "Container Limits" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU limits set and constrains limits to be within the specified maximum values. @@ -65,7 +65,7 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -162,7 +162,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/library/general/containerrequests/template.yaml b/library/general/containerrequests/template.yaml index 5a78959bb..a67e8b786 100644 --- a/library/general/containerrequests/template.yaml +++ b/library/general/containerrequests/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8scontainerrequests annotations: metadata.gatekeeper.sh/title: "Container Requests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU requests set and constrains requests to be within the specified maximum values. @@ -65,7 +65,7 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -162,7 +162,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/library/general/containerresourceratios/template.yaml b/library/general/containerresourceratios/template.yaml index 5b79df483..94a9753aa 100644 --- a/library/general/containerresourceratios/template.yaml +++ b/library/general/containerresourceratios/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8scontainerratios annotations: metadata.gatekeeper.sh/title: "Container Ratios" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Sets a maximum ratio for container resource limits to requests. @@ -68,14 +68,14 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+$", orig) + regex.match("^[0-9]+$", orig) new := to_number(orig) * 1000 } canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+[.][0-9]+$", orig) + regex.match("^[0-9]+[.][0-9]+$", orig) new := to_number(orig) * 1000 } @@ -172,7 +172,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/library/general/disallowedtags/template.yaml b/library/general/disallowedtags/template.yaml index 79100e1ca..43651dd0c 100644 --- a/library/general/disallowedtags/template.yaml +++ b/library/general/disallowedtags/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8sdisallowedtags annotations: metadata.gatekeeper.sh/title: "Disallow tags" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to have an image tag different from the ones in the specified list. @@ -44,16 +44,15 @@ spec: violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tags := [forbid | tag = input.parameters.tags[_] ; forbid = endswith(container.image, concat(":", ["", tag]))] - any(tags) + tags := [tag_with_prefix | tag := input.parameters.tags[_]; tag_with_prefix := concat(":", ["", tag])] + strings.any_suffix_match(container.image, tags) msg := sprintf("container <%v> uses a disallowed tag <%v>; disallowed tags are %v", [container.name, container.image, input.parameters.tags]) } violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tag := [contains(container.image, ":")] - not all(tag) + not contains(container.image, ":") msg := sprintf("container <%v> didn't specify an image tag <%v>", [container.name, container.image]) } diff --git a/library/general/ephemeralstoragelimit/template.yaml b/library/general/ephemeralstoragelimit/template.yaml index 2f7bf1b2b..a9dca71d2 100644 --- a/library/general/ephemeralstoragelimit/template.yaml +++ b/library/general/ephemeralstoragelimit/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8scontainerephemeralstoragelimit annotations: metadata.gatekeeper.sh/title: "Container ephemeral storage limit" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires containers to have an ephemeral storage limit set and constrains the limit to be within the specified maximum values. @@ -146,7 +146,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * storage_multiple(suffix) } diff --git a/library/general/httpsonly/template.yaml b/library/general/httpsonly/template.yaml index c7698c150..5293fe72c 100644 --- a/library/general/httpsonly/template.yaml +++ b/library/general/httpsonly/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8shttpsonly annotations: metadata.gatekeeper.sh/title: "HTTPS Only" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires Ingress resources to be HTTPS only. Ingress resources must include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. @@ -39,19 +39,19 @@ spec: violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not https_complete(ingress) - not tls_is_optional(ingress) + not tls_is_optional msg := sprintf("Ingress should be https. tls configuration and allow-http=false annotation are required for %v", [ingress.metadata.name]) } violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not annotation_complete(ingress) - not tls_not_optional(ingress) + tls_is_optional msg := sprintf("Ingress should be https. The allow-http=false annotation is required for %v", [ingress.metadata.name]) } @@ -65,15 +65,7 @@ spec: ingress.metadata.annotations["kubernetes.io/ingress.allow-http"] == "false" } - tls_is_optional(ingress) = true { + tls_is_optional { parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - is_boolean(tlsOptional) - true == tlsOptional - } - - tls_not_optional(ingress) = true { - parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - true != tlsOptional + object.get(parameters, "tlsOptional", false) == true } diff --git a/library/general/imagedigests/template.yaml b/library/general/imagedigests/template.yaml index 49ac46bad..e00a4b608 100644 --- a/library/general/imagedigests/template.yaml +++ b/library/general/imagedigests/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8simagedigests annotations: metadata.gatekeeper.sh/title: "Image Digests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to contain a digest. @@ -42,24 +42,21 @@ spec: violation[{"msg": msg}] { container := input.review.object.spec.containers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } libs: diff --git a/library/general/noupdateserviceaccount/template.yaml b/library/general/noupdateserviceaccount/template.yaml index 1855c205d..782a0d313 100644 --- a/library/general/noupdateserviceaccount/template.yaml +++ b/library/general/noupdateserviceaccount/template.yaml @@ -4,7 +4,7 @@ metadata: name: noupdateserviceaccount annotations: metadata.gatekeeper.sh/title: "Block updating Service Account" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: "Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode." spec: crd: @@ -30,13 +30,15 @@ spec: rego: | package noupdateserviceaccount - privileged(userInfo, allowedUsers, allowedGroups) { + privileged(userInfo, allowedUsers, _) { # Allow if the user is in allowedUsers. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. username := object.get(userInfo, "username", "") allowedUsers[_] == username - } { + } + + privileged(userInfo, _, allowedGroups) { # Allow if the user's groups intersect allowedGroups. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. diff --git a/library/general/replicalimits/template.yaml b/library/general/replicalimits/template.yaml index 540abc67f..2e44fb2c1 100644 --- a/library/general/replicalimits/template.yaml +++ b/library/general/replicalimits/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8sreplicalimits annotations: metadata.gatekeeper.sh/title: "Replica Limits" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires that objects with the field `spec.replicas` (Deployments, ReplicaSets, etc.) specify a number of replicas within defined ranges. @@ -46,7 +46,7 @@ spec: } input_replica_limit(spec) { - provided := input.review.object.spec.replicas + provided := spec.replicas count(input.parameters.ranges) > 0 range := input.parameters.ranges[_] value_within_range(range, provided) diff --git a/library/general/requiredannotations/template.yaml b/library/general/requiredannotations/template.yaml index f4a15e930..634acb181 100644 --- a/library/general/requiredannotations/template.yaml +++ b/library/general/requiredannotations/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8srequiredannotations annotations: metadata.gatekeeper.sh/title: "Required Annotations" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified annotations, with values matching provided regular expressions. @@ -54,6 +54,6 @@ spec: expected := input.parameters.annotations[_] expected.key == key expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) msg := sprintf("Annotation <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) } diff --git a/library/general/requiredlabels/template.yaml b/library/general/requiredlabels/template.yaml index 77323da67..aa865394c 100644 --- a/library/general/requiredlabels/template.yaml +++ b/library/general/requiredlabels/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8srequiredlabels annotations: metadata.gatekeeper.sh/title: "Required Labels" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified labels, with values matching provided regular expressions. @@ -41,14 +41,11 @@ spec: rego: | package k8srequiredlabels - get_message(parameters, _default) = msg { + get_message(parameters, _default) := _default { not parameters.message - msg := _default } - get_message(parameters, _default) = msg { - msg := parameters.message - } + get_message(parameters, _) := parameters.message violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} @@ -65,7 +62,7 @@ spec: expected.key == key # do not match if allowedRegex is not defined, or is an empty string expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) def_msg := sprintf("Label <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) msg := get_message(input.parameters, def_msg) } diff --git a/library/general/uniqueingresshost/template.yaml b/library/general/uniqueingresshost/template.yaml index 2f6c2efa6..c534b2a20 100644 --- a/library/general/uniqueingresshost/template.yaml +++ b/library/general/uniqueingresshost/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/version: 1.0.4 metadata.gatekeeper.sh/requires-sync-data: | "[ [ @@ -42,10 +42,10 @@ spec: violation[{"msg": msg}] { input.review.kind.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)$", input.review.kind.group) + regex.match("^(extensions|networking.k8s.io)$", input.review.kind.group) host := input.review.object.spec.rules[_].host other := data.inventory.namespace[_][otherapiversion]["Ingress"][name] - re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion) + regex.match("^(extensions|networking.k8s.io)/.+$", otherapiversion) other.spec.rules[_].host == host not identical(other, input.review) msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host]) diff --git a/library/pod-security-policy/capabilities/template.yaml b/library/pod-security-policy/capabilities/template.yaml index 0df32e927..2501a1538 100644 --- a/library/pod-security-policy/capabilities/template.yaml +++ b/library/pod-security-policy/capabilities/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspcapabilities annotations: metadata.gatekeeper.sh/title: "Capabilities" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a @@ -125,14 +125,11 @@ spec: count(all - dropped) > 0 } - get_default(obj, param, _default) = out { - out = obj[param] - } + get_default(obj, param, _) := obj[param] - get_default(obj, param, _default) = out { + get_default(obj, param, _default) := _default { not obj[param] not obj[param] == false - out = _default } libs: - | diff --git a/library/pod-security-policy/forbidden-sysctls/template.yaml b/library/pod-security-policy/forbidden-sysctls/template.yaml index 3d3c1d9a0..053c0eae5 100644 --- a/library/pod-security-policy/forbidden-sysctls/template.yaml +++ b/library/pod-security-policy/forbidden-sysctls/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspforbiddensysctls annotations: metadata.gatekeeper.sh/title: "Forbidden Sysctls" - metadata.gatekeeper.sh/version: 1.1.2 + metadata.gatekeeper.sh/version: 1.1.3 description: >- Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. @@ -63,7 +63,7 @@ spec: } # * may be used to forbid all sysctls - forbidden_sysctl(sysctl) { + forbidden_sysctl(_) { input.parameters.forbiddenSysctls[_] == "*" } @@ -78,7 +78,7 @@ spec: } # * may be used to allow all sysctls - allowed_sysctl(sysctl) { + allowed_sysctl(_) { input.parameters.allowedSysctls[_] == "*" } diff --git a/library/pod-security-policy/fsgroup/template.yaml b/library/pod-security-policy/fsgroup/template.yaml index d3f56af81..4e1b9449a 100644 --- a/library/pod-security-policy/fsgroup/template.yaml +++ b/library/pod-security-policy/fsgroup/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspfsgroup annotations: metadata.gatekeeper.sh/title: "FS Group" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls allocating an FSGroup that owns the Pod's volumes. Corresponds to the `fsGroup` field in a PodSecurityPolicy. For more information, see @@ -58,7 +58,7 @@ spec: msg := sprintf("The provided pod spec fsGroup is not allowed, pod: %v. Allowed fsGroup: %v", [input.review.object.metadata.name, input.parameters]) } - input_fsGroup_allowed(spec) { + input_fsGroup_allowed(_) { # RunAsAny - No range is required. Allows any fsGroup ID to be specified. input.parameters.rule == "RunAsAny" } diff --git a/library/pod-security-policy/host-filesystem/template.yaml b/library/pod-security-policy/host-filesystem/template.yaml index 2ef796fd4..5f506c351 100644 --- a/library/pod-security-policy/host-filesystem/template.yaml +++ b/library/pod-security-policy/host-filesystem/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spsphostfilesystem annotations: metadata.gatekeeper.sh/title: "Host Filesystem" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of the host filesystem. Corresponds to the `allowedHostPaths` field in a PodSecurityPolicy. For more information, @@ -54,7 +54,7 @@ spec: msg := sprintf("HostPath volume %v is not allowed, pod: %v. Allowed path: %v", [volume, input.review.object.metadata.name, allowedPaths]) } - input_hostpath_violation(allowedPaths, volume) { + input_hostpath_violation(allowedPaths, _) { # An empty list means all host paths are blocked allowedPaths == [] } diff --git a/library/pod-security-policy/host-network-ports/template.yaml b/library/pod-security-policy/host-network-ports/template.yaml index 31a9d9e56..0f04aae03 100644 --- a/library/pod-security-policy/host-network-ports/template.yaml +++ b/library/pod-security-policy/host-network-ports/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spsphostnetworkingports annotations: metadata.gatekeeper.sh/title: "Host Networking Ports" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and @@ -65,12 +65,12 @@ spec: o.spec.hostNetwork } - input_share_hostnetwork(o) { + input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort < input.parameters.min } - input_share_hostnetwork(o) { + input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort > input.parameters.max } diff --git a/library/pod-security-policy/proc-mount/template.yaml b/library/pod-security-policy/proc-mount/template.yaml index bbf2244da..5fb816793 100644 --- a/library/pod-security-policy/proc-mount/template.yaml +++ b/library/pod-security-policy/proc-mount/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspprocmount annotations: metadata.gatekeeper.sh/title: "Proc Mount" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.0.3 description: >- Controls the allowed `procMount` types for the container. Corresponds to the `allowedProcMountTypes` field in a PodSecurityPolicy. For more @@ -68,7 +68,7 @@ spec: allowedProcMount == "default" lower(c.securityContext.procMount) == "default" } - input_proc_mount_type_allowed(allowedProcMount, c) { + input_proc_mount_type_allowed(allowedProcMount, _) { allowedProcMount == "unmasked" } diff --git a/library/pod-security-policy/seccomp/template.yaml b/library/pod-security-policy/seccomp/template.yaml index 3ed313929..d252a1ace 100644 --- a/library/pod-security-policy/seccomp/template.yaml +++ b/library/pod-security-policy/seccomp/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspseccomp annotations: metadata.gatekeeper.sh/title: "Seccomp" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Controls the seccomp profile used by containers. Corresponds to the `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on @@ -98,7 +98,7 @@ spec: msg := get_message(result.profile, result.file, name, result.location, allowed_profiles) } - get_message(profile, file, name, location, allowed_profiles) = message { + get_message(profile, _, name, location, allowed_profiles) = message { not profile == "Localhost" message := sprintf("Seccomp profile '%v' is not allowed for container '%v'. Found at: %v. Allowed profiles: %v", [profile, name, location, allowed_profiles]) } @@ -121,7 +121,7 @@ spec: } # Simple allowed Profiles - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { not startswith(lower(profile), "localhost") profile == allowed[_] } @@ -136,20 +136,20 @@ spec: } # seccomp Localhost with wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { profile == "Localhost" input_wildcard_allowed_files profile == allowed[_] } # annotation localhost with wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { "localhost/*" == allowed[_] startswith(profile, "localhost/") } # annotation localhost without wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { startswith(profile, "localhost/") profile == allowed[_] } diff --git a/library/pod-security-policy/selinux/template.yaml b/library/pod-security-policy/selinux/template.yaml index 61729eceb..a2a502b16 100644 --- a/library/pod-security-policy/selinux/template.yaml +++ b/library/pod-security-policy/selinux/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspselinuxv2 annotations: metadata.gatekeeper.sh/title: "SELinux V2" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Defines an allow-list of seLinuxOptions configurations for pod containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. @@ -94,7 +94,7 @@ spec: field_allowed(field, options, params) { params[field] == options[field] } - field_allowed(field, options, params) { + field_allowed(field, options, _) { not has_field(options, field) } diff --git a/library/pod-security-policy/users/template.yaml b/library/pod-security-policy/users/template.yaml index 1e572443e..613fc9307 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.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and @@ -182,11 +182,11 @@ spec: msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) } - accept_users("RunAsAny", provided_user) {true} + accept_users("RunAsAny", _) - accept_users("MustRunAsNonRoot", provided_user) = res {res := provided_user != 0} + accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 - accept_users("MustRunAs", provided_user) = res { + accept_users("MustRunAs", provided_user) := res { ranges := input.parameters.runAsUser.ranges res := is_in_range(provided_user, ranges) } @@ -215,18 +215,15 @@ spec: msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) } - accept_value("RunAsAny", provided_value, ranges) {true} + accept_value("RunAsAny", _, _) - accept_value("MayRunAs", provided_value, ranges) = res { res := is_in_range(provided_value, ranges)} + accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - accept_value("MustRunAs", provided_value, ranges) = res { res := 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, review) = out { - container_value := get_seccontext_field(field, container) - out := container_value - } + 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 { diff --git a/library/pod-security-policy/volumes/template.yaml b/library/pod-security-policy/volumes/template.yaml index 458cb3178..74165c8f4 100644 --- a/library/pod-security-policy/volumes/template.yaml +++ b/library/pod-security-policy/volumes/template.yaml @@ -4,7 +4,7 @@ metadata: name: k8spspvolumetypes annotations: metadata.gatekeeper.sh/title: "Volume Types" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Restricts mountable volume types to those specified by the user. Corresponds to the `volumes` field in a PodSecurityPolicy. For more @@ -48,7 +48,7 @@ spec: } # * may be used to allow all volume types - input_volume_type_allowed(field) { + input_volume_type_allowed(_) { input.parameters.volumes[_] == "*" } diff --git a/src/general/allowedrepos/constraint.tmpl b/src/general/allowedrepos/constraint.tmpl index 52dac8a0d..8f0b53fd3 100644 --- a/src/general/allowedrepos/constraint.tmpl +++ b/src/general/allowedrepos/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8sallowedrepos annotations: metadata.gatekeeper.sh/title: "Allowed Repositories" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to begin with a string from the specified list. spec: diff --git a/src/general/allowedrepos/src.rego b/src/general/allowedrepos/src.rego index 649dafb77..37ae159de 100644 --- a/src/general/allowedrepos/src.rego +++ b/src/general/allowedrepos/src.rego @@ -2,21 +2,18 @@ package k8sallowedrepos violation[{"msg": msg}] { container := input.review.object.spec.containers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } diff --git a/src/general/allowedrepos/src_test.rego b/src/general/allowedrepos/src_test.rego index 7eede7c23..932bc4dc0 100644 --- a/src/general/allowedrepos/src_test.rego +++ b/src/general/allowedrepos/src_test.rego @@ -1,75 +1,75 @@ package k8sallowedrepos test_input_allowed_container { - input := { "review": input_review(input_container_allowed), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_allowed), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_container_x2 { - input := { "review": input_review(input_container_allowed), "parameters": {"repos": ["other", "allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_allowed), "parameters": {"repos": ["other", "allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_container { - input := { "review": input_review(input_container_dual_allowed), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_dual_allowed), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_container { - input := { "review": input_review(input_container_denied), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_x2 { - input := { "review": input_review(input_container_denied), "parameters": {"repos": ["other", "allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied), "parameters": {"repos": ["other", "allowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container { - input := { "review": input_review(input_container_dual_denied), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_dual_denied), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 1 } # init containers test_input_allowed_container { - input := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_container_x2 { - input := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["other", "allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["other", "allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_container { - input := { "review": input_init_review(input_container_dual_allowed), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_allowed), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_container { - input := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_x2 { - input := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["other", "allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["other", "allowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container { - input := { "review": input_init_review(input_container_dual_denied), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_denied), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 1 } diff --git a/src/general/automount-serviceaccount-token/src_test.rego b/src/general/automount-serviceaccount-token/src_test.rego index ec2c75ea2..ef78ba609 100644 --- a/src/general/automount-serviceaccount-token/src_test.rego +++ b/src/general/automount-serviceaccount-token/src_test.rego @@ -1,26 +1,26 @@ package k8sautomountserviceaccounttoken test_input_pod_not_automountserviceaccounttoken_allowed { - input := {"review": input_review_disabled_automountserviceaccounttoken} - results := violation with input as input + inp := {"review": input_review_disabled_automountserviceaccounttoken} + results := violation with input as inp count(results) == 0 } test_input_pod_automountserviceaccounttoken_not_allowed { - input := {"review": input_review_enabled_automountserviceaccounttoken} - results := violation with input as input + inp := {"review": input_review_enabled_automountserviceaccounttoken} + results := violation with input as inp count(results) > 0 } test_input_pod_automountserviceaccounttoken_not_defined { - input := {"review": input_review_no_automountserviceaccounttoken_defined_and_enabled_volumemount} - results := violation with input as input + inp := {"review": input_review_no_automountserviceaccounttoken_defined_and_enabled_volumemount} + results := violation with input as inp count(results) > 0 } test_update { - input := {"review": object.union(input_review_enabled_automountserviceaccounttoken, {"operation": "UPDATE"})} - results := violation with input as input + inp := {"review": object.union(input_review_enabled_automountserviceaccounttoken, {"operation": "UPDATE"})} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/block-endpoint-edit-default-role/src_test.rego b/src/general/block-endpoint-edit-default-role/src_test.rego index 8cbe0118b..5eda05194 100644 --- a/src/general/block-endpoint-edit-default-role/src_test.rego +++ b/src/general/block-endpoint-edit-default-role/src_test.rego @@ -1,32 +1,32 @@ package k8sblockendpointeditdefaultrole test_input_no_endpoints_edit_role_allow { - input := { "review": input_review_withoutendpoints } - results := violation with input as input + inp := { "review": input_review_withoutendpoints } + results := violation with input as inp count(results) == 0 } test_input_endpoints_create_role_not_allow { - input := { "review": input_review_with_endpoints_create } - results := violation with input as input + inp := { "review": input_review_with_endpoints_create } + results := violation with input as inp count(results) == 1 } test_input_endpoints_update_role_not_allow { - input := { "review": input_review_with_endpoints_update } - results := violation with input as input + inp := { "review": input_review_with_endpoints_update } + results := violation with input as inp count(results) == 1 } test_input_endpoints_patch_role_not_allow { - input := { "review": input_review_with_endpoints_patch } - results := violation with input as input + inp := { "review": input_review_with_endpoints_patch } + results := violation with input as inp count(results) == 1 } test_input_endpoints_delete_role_allow { - input := { "review": input_review_with_endpoints_delete } - results := violation with input as input + inp := { "review": input_review_with_endpoints_delete } + results := violation with input as inp count(results) == 0 } diff --git a/src/general/block-loadbalancer-services/src_test.rego b/src/general/block-loadbalancer-services/src_test.rego index 1f2272756..208f6af98 100644 --- a/src/general/block-loadbalancer-services/src_test.rego +++ b/src/general/block-loadbalancer-services/src_test.rego @@ -1,7 +1,7 @@ package k8sblockloadbalancer test_block_load_balancer { - input := { + inp := { "review": { "kind": {"kind": "Service"}, "object": { @@ -16,11 +16,11 @@ test_block_load_balancer { } } } - result := violation with input as input + result := violation with input as inp count(result) == 1 } test_allow_other_service_types { - input := { + inp := { "review": { "kind": {"kind": "Service"}, "object": { @@ -35,6 +35,6 @@ test_allow_other_service_types { } } } - result := violation with input as input + result := violation with input as inp count(result) == 0 } diff --git a/src/general/block-nodeport-services/src_test.rego b/src/general/block-nodeport-services/src_test.rego index caf13bee7..c28c314ef 100644 --- a/src/general/block-nodeport-services/src_test.rego +++ b/src/general/block-nodeport-services/src_test.rego @@ -1,7 +1,7 @@ package k8sblocknodeport test_block_node_port { - input := { + inp := { "review": { "kind": {"kind": "Service"}, "object": { @@ -16,11 +16,11 @@ test_block_node_port { } } } - result := violation with input as input + result := violation with input as inp count(result) == 1 } test_allow_other_service_types { - input := { + inp := { "review": { "kind": {"kind": "Service"}, "object": { @@ -35,6 +35,6 @@ test_allow_other_service_types { } } } - result := violation with input as input + result := violation with input as inp count(result) == 0 } diff --git a/src/general/block-wildcard-ingress/src_test.rego b/src/general/block-wildcard-ingress/src_test.rego index 9e435988b..4030e8bcf 100644 --- a/src/general/block-wildcard-ingress/src_test.rego +++ b/src/general/block-wildcard-ingress/src_test.rego @@ -1,32 +1,32 @@ package K8sBlockWildcardIngress test_input_ingress_allowed_host { - input := { "review": input_review(input_ingress_allowed_host) } - results := violation with input as input + inp := { "review": input_review(input_ingress_allowed_host) } + results := violation with input as inp count(results) == 0 } test_input_ingress_disallowed_wildcard_host { - input := { "review": input_review(input_ingress_disallowed_wildcard_host) } - results := violation with input as input + inp := { "review": input_review(input_ingress_disallowed_wildcard_host) } + results := violation with input as inp count(results) == 1 } test_input_ingress_disallowed_empty_host { - input := { "review": input_review(input_ingress_disallowed_empty_host) } - results := violation with input as input + inp := { "review": input_review(input_ingress_disallowed_empty_host) } + results := violation with input as inp count(results) == 1 } test_input_ingress_disallowed_empty_host { - input := { "review": input_review(input_ingress_disallowed_empty_host) } - results := violation with input as input + inp := { "review": input_review(input_ingress_disallowed_empty_host) } + results := violation with input as inp count(results) == 1 } test_input_ingress_no_rules { - input := { "review": input_review(input_ingress_no_rules) } - results := violation with input as input + inp := { "review": input_review(input_ingress_no_rules) } + results := violation with input as inp count(results) == 1 } diff --git a/src/general/containerlimits/constraint.tmpl b/src/general/containerlimits/constraint.tmpl index 507029b46..33b5b791d 100644 --- a/src/general/containerlimits/constraint.tmpl +++ b/src/general/containerlimits/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8scontainerlimits annotations: metadata.gatekeeper.sh/title: "Container Limits" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU limits set and constrains limits to be within the specified maximum values. diff --git a/src/general/containerlimits/src.rego b/src/general/containerlimits/src.rego index 9124c886b..53dcaa0c6 100644 --- a/src/general/containerlimits/src.rego +++ b/src/general/containerlimits/src.rego @@ -24,7 +24,7 @@ canonify_cpu(orig) = new { canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -121,7 +121,7 @@ canonify_mem(orig) = new { not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/src/general/containerlimits/src_test.rego b/src/general/containerlimits/src_test.rego index eb879cc72..d3f983870 100644 --- a/src/general/containerlimits/src_test.rego +++ b/src/general/containerlimits/src_test.rego @@ -1,187 +1,187 @@ package k8scontainerlimits test_input_no_violations_int { - input := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 20, "cpu": 40}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 20, "cpu": 40}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str { - input := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "20", "cpu": "40"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "20", "cpu": "40"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str_small { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_cpu_scale { - input := {"review": review([ctr("a", "1", "2m")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2m")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_violations_int { - input := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 5, "cpu": 10}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 5, "cpu": 10}} + results := violation with input as inp count(results) == 2 } test_input_violations_mem_int_v_str { - input := {"review": review([ctr("a", 10, "4")]), "parameters": {"memory": "1000m", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, "4")]), "parameters": {"memory": "1000m", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_str { - input := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "5", "cpu": "10"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "5", "cpu": "10"}} + results := violation with input as inp count(results) == 2 } test_input_violations_str_small { - input := {"review": review([ctr("a", "5", "6")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "5", "6")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_input_violations_cpu_scale { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4m"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4m"}} + results := violation with input as inp count(results) == 1 } test_no_parse_cpu { - input := {"review": review([ctr("a", "1", "212asdf")]), "parameters": {"memory": "2", "cpu": "4m"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "212asdf")]), "parameters": {"memory": "2", "cpu": "4m"}} + results := violation with input as inp count(results) == 1 } test_no_parse_ram { - input := {"review": review([ctr("a", "1asdf", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1asdf", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_1_bad_cpu { - input := {"review": review([ctr("a", "1", "2"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_2_bad_cpu { - input := {"review": review([ctr("a", "1", "9"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "9"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_1_bad_ram { - input := {"review": review([ctr("a", "1", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_2_bad_ram { - input := {"review": review([ctr("a", "9", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "9", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_no_ram_limit { - input := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_cpu_limit { - input := {"review": review([{"name": "a", "resources": {"limits": {"memory": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"limits": {"memory": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_limit { - input := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_resources { - input := {"review": review([{"name": "a"}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a"}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_init_containers_checked { - input := {"review": init_review([ctr("a", "5", "5"), ctr("b", "5", "5")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": init_review([ctr("a", "5", "5"), ctr("b", "5", "5")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 4 } # MEM SCALE TESTS test_input_no_violations_mem_K { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_violations_mem_m { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1m", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1m", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_K { - input := {"review": review([ctr("a", "1k", "2")]), "parameters": {"memory": "1", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1k", "2")]), "parameters": {"memory": "1", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_M { - input := {"review": review([ctr("a", "1M", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1M", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_G { - input := {"review": review([ctr("a", "1G", "2")]), "parameters": {"memory": "1M", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1G", "2")]), "parameters": {"memory": "1M", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_T { - input := {"review": review([ctr("a", "1T", "2")]), "parameters": {"memory": "1G", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1T", "2")]), "parameters": {"memory": "1G", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_P { - input := {"review": review([ctr("a", "1P", "2")]), "parameters": {"memory": "1T", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1P", "2")]), "parameters": {"memory": "1T", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_E { - input := {"review": review([ctr("a", "1E", "2")]), "parameters": {"memory": "1P", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1E", "2")]), "parameters": {"memory": "1P", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ki { - input := {"review": review([ctr("a", "1Ki", "2")]), "parameters": {"memory": "1", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ki", "2")]), "parameters": {"memory": "1", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Mi { - input := {"review": review([ctr("a", "1Mi", "2")]), "parameters": {"memory": "1Ki", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Mi", "2")]), "parameters": {"memory": "1Ki", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Gi { - input := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1Mi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1Mi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_decimal_mem_Gi { - input := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1.5Mi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1.5Mi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ti { - input := {"review": review([ctr("a", "1Ti", "2")]), "parameters": {"memory": "1Gi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ti", "2")]), "parameters": {"memory": "1Gi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Pi { - input := {"review": review([ctr("a", "1Pi", "2")]), "parameters": {"memory": "1Ti", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Pi", "2")]), "parameters": {"memory": "1Ti", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei { - input := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"memory": "1Pi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"memory": "1Pi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei_with_exemption { - input := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"exemptImages": ["nginx"], "memory": "1Pi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"exemptImages": ["nginx"], "memory": "1Pi", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/containerrequests/constraint.tmpl b/src/general/containerrequests/constraint.tmpl index ea4189138..fb96b6d10 100644 --- a/src/general/containerrequests/constraint.tmpl +++ b/src/general/containerrequests/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8scontainerrequests annotations: metadata.gatekeeper.sh/title: "Container Requests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU requests set and constrains requests to be within the specified maximum values. diff --git a/src/general/containerrequests/src.rego b/src/general/containerrequests/src.rego index 79e1e65ab..94ac1f831 100644 --- a/src/general/containerrequests/src.rego +++ b/src/general/containerrequests/src.rego @@ -24,7 +24,7 @@ canonify_cpu(orig) = new { canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -121,7 +121,7 @@ canonify_mem(orig) = new { not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/src/general/containerrequests/src_test.rego b/src/general/containerrequests/src_test.rego index b6c8d7412..4479e825f 100644 --- a/src/general/containerrequests/src_test.rego +++ b/src/general/containerrequests/src_test.rego @@ -1,187 +1,187 @@ package k8scontainerrequests test_input_no_violations_int { - input := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 20, "cpu": 40}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 20, "cpu": 40}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str { - input := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "20", "cpu": "40"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "20", "cpu": "40"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str_small { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_cpu_scale { - input := {"review": review([ctr("a", "1", "2m")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2m")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_violations_int { - input := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 5, "cpu": 10}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, 20)]), "parameters": {"memory": 5, "cpu": 10}} + results := violation with input as inp count(results) == 2 } test_input_violations_mem_int_v_str { - input := {"review": review([ctr("a", 10, "4")]), "parameters": {"memory": "1000m", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, "4")]), "parameters": {"memory": "1000m", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_str { - input := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "5", "cpu": "10"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20")]), "parameters": {"memory": "5", "cpu": "10"}} + results := violation with input as inp count(results) == 2 } test_input_violations_str_small { - input := {"review": review([ctr("a", "5", "6")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "5", "6")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_input_violations_cpu_scale { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4m"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "2", "cpu": "4m"}} + results := violation with input as inp count(results) == 1 } test_no_parse_cpu { - input := {"review": review([ctr("a", "1", "212asdf")]), "parameters": {"memory": "2", "cpu": "4m"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "212asdf")]), "parameters": {"memory": "2", "cpu": "4m"}} + results := violation with input as inp count(results) == 1 } test_no_parse_ram { - input := {"review": review([ctr("a", "1asdf", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1asdf", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_1_bad_cpu { - input := {"review": review([ctr("a", "1", "2"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_2_bad_cpu { - input := {"review": review([ctr("a", "1", "9"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "9"), ctr("b", "1", "8")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_1_bad_ram { - input := {"review": review([ctr("a", "1", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_2_bad_ram { - input := {"review": review([ctr("a", "9", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "9", "2"), ctr("b", "8", "2")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 2 } test_no_ram_request { - input := {"review": review([{"name": "a", "resources": {"requests": {"cpu": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"requests": {"cpu": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_cpu_request { - input := {"review": review([{"name": "a", "resources": {"requests": {"memory": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"requests": {"memory": 1}}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_request { - input := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_no_resources { - input := {"review": review([{"name": "a"}]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a"}]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_init_containers_checked { - input := {"review": init_review([ctr("a", "5", "5"), ctr("b", "5", "5")]), "parameters": {"memory": "2", "cpu": "4"}} - results := violation with input as input + inp := {"review": init_review([ctr("a", "5", "5"), ctr("b", "5", "5")]), "parameters": {"memory": "2", "cpu": "4"}} + results := violation with input as inp count(results) == 4 } # MEM SCALE TESTS test_input_no_violations_mem_K { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } test_input_violations_mem_m { - input := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1m", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2")]), "parameters": {"memory": "1m", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_K { - input := {"review": review([ctr("a", "1k", "2")]), "parameters": {"memory": "1", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1k", "2")]), "parameters": {"memory": "1", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_M { - input := {"review": review([ctr("a", "1M", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1M", "2")]), "parameters": {"memory": "1k", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_G { - input := {"review": review([ctr("a", "1G", "2")]), "parameters": {"memory": "1M", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1G", "2")]), "parameters": {"memory": "1M", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_T { - input := {"review": review([ctr("a", "1T", "2")]), "parameters": {"memory": "1G", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1T", "2")]), "parameters": {"memory": "1G", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_P { - input := {"review": review([ctr("a", "1P", "2")]), "parameters": {"memory": "1T", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1P", "2")]), "parameters": {"memory": "1T", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_E { - input := {"review": review([ctr("a", "1E", "2")]), "parameters": {"memory": "1P", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1E", "2")]), "parameters": {"memory": "1P", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ki { - input := {"review": review([ctr("a", "1Ki", "2")]), "parameters": {"memory": "1", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ki", "2")]), "parameters": {"memory": "1", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Mi { - input := {"review": review([ctr("a", "1Mi", "2")]), "parameters": {"memory": "1Ki", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Mi", "2")]), "parameters": {"memory": "1Ki", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Gi { - input := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1Mi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1Mi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_decimal_mem_Gi { - input := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1.5Mi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi", "2")]), "parameters": {"memory": "1.5Mi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ti { - input := {"review": review([ctr("a", "1Ti", "2")]), "parameters": {"memory": "1Gi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ti", "2")]), "parameters": {"memory": "1Gi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Pi { - input := {"review": review([ctr("a", "1Pi", "2")]), "parameters": {"memory": "1Ti", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Pi", "2")]), "parameters": {"memory": "1Ti", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei { - input := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"memory": "1Pi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"memory": "1Pi", "cpu": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei_with_exemption { - input := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"exemptImages": ["nginx"], "memory": "1Pi", "cpu": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2")]), "parameters": {"exemptImages": ["nginx"], "memory": "1Pi", "cpu": "4"}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/containerresourceratios/constraint.tmpl b/src/general/containerresourceratios/constraint.tmpl index 4de6e9ad5..88a838d45 100644 --- a/src/general/containerresourceratios/constraint.tmpl +++ b/src/general/containerresourceratios/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8scontainerratios annotations: metadata.gatekeeper.sh/title: "Container Ratios" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Sets a maximum ratio for container resource limits to requests. diff --git a/src/general/containerresourceratios/src.rego b/src/general/containerresourceratios/src.rego index a31366235..9d269e681 100644 --- a/src/general/containerresourceratios/src.rego +++ b/src/general/containerresourceratios/src.rego @@ -24,14 +24,14 @@ canonify_cpu(orig) = new { canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+$", orig) + regex.match("^[0-9]+$", orig) new := to_number(orig) * 1000 } canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+[.][0-9]+$", orig) + regex.match("^[0-9]+[.][0-9]+$", orig) new := to_number(orig) * 1000 } @@ -128,7 +128,7 @@ canonify_mem(orig) = new { not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/src/general/containerresourceratios/src_test.rego b/src/general/containerresourceratios/src_test.rego index e73bca378..1148390c9 100644 --- a/src/general/containerresourceratios/src_test.rego +++ b/src/general/containerresourceratios/src_test.rego @@ -1,269 +1,269 @@ package k8scontainerratios test_input_no_violations_int { - input := {"review": review([ctr("a", 10, 20, 5, 10)]), "parameters": {"ratio": 2}} - results := violation with input as input + inp := {"review": review([ctr("a", 10, 20, 5, 10)]), "parameters": {"ratio": 2}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_no_violations_str { - input := {"review": review([ctr("a", "10", "20", "5", "10")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20", "5", "10")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_no_violations_str_small { - input := {"review": review([ctr("a", "1", "2", "1", "1")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1", "1")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_no_violations_cpu_scale { - input := {"review": review([ctr("a", "2", "4m", "1", "2m")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "2", "4m", "1", "2m")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_no_violations_cpu_decimal { - input := {"review": review([ctr("a", "2", "3", "1", "1.5")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "2", "3", "1", "1.5")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_violations_int { - input := {"review": review([ctr("a", 20, 40, 5, 10)]), "parameters": {"ratio": 2}} - results := violation with input as input + inp := {"review": review([ctr("a", 20, 40, 5, 10)]), "parameters": {"ratio": 2}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_input_violations_mem_int_v_str { - input := {"review": review([ctr("a", 1, "3", "1m", "1.5")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", 1, "3", "1m", "1.5")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_input_violations_str { - input := {"review": review([ctr("a", "10", "20", "2", "4")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10", "20", "2", "4")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_input_violations_str_small { - input := {"review": review([ctr("a", "5", "6", "1", "1")]), "parameters": {"ratio": "3"}} - results := violation with input as input + inp := {"review": review([ctr("a", "5", "6", "1", "1")]), "parameters": {"ratio": "3"}} + results := violation with input as inp count(results) == 2 } test_input_violations_cpu_scale { - input := {"review": review([ctr("a", "1", "2", "1", "4m")]), "parameters": {"ratio": "10"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1", "4m")]), "parameters": {"ratio": "10"}} + results := violation with input as inp count(results) == 1 } test_input_violations_cpu_decimal { - input := {"review": review([ctr("a", "1", "2", "1", "0.5")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1", "0.5")]), "parameters": {"ratio": "2"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_no_parse_cpu_limits { - input := {"review": review([ctr("a", "1", "212asdf", "2", "2")]), "parameters": {"raio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "212asdf", "2", "2")]), "parameters": {"raio": "4"}} + results := violation with input as inp count(results) == 1 } test_no_parse_cpu_requests { - input := {"review": review([ctr("a", "1", "2", "2", "212asdf")]), "parameters": {"raio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "2", "212asdf")]), "parameters": {"raio": "4"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_no_parse_cpu_requests_and_limits { - input := {"review": review([ctr("a", "1", "212asdf", "2", "212asdf")]), "parameters": {"raio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "212asdf", "2", "212asdf")]), "parameters": {"raio": "4"}} + results := violation with input as inp count(results) == 2 } test_no_parse_ram_limits { - input := {"review": review([ctr("a", "1asdf", "2", "1", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1asdf", "2", "1", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_no_parse_ram_requests { - input := {"review": review([ctr("a", "1", "2", "1asdf", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1asdf", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_no_parse_ram_requests_and_limits { - input := {"review": review([ctr("a", "1asdf", "2", "1asdf", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1asdf", "2", "1asdf", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 2 } test_1_bad_cpu { - input := {"review": review([ctr("a", "1", "2", "1", "2"), ctr("b", "1", "8", "1", "2")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1", "2"), ctr("b", "1", "8", "1", "2")]), "parameters": {"ratio": "2"}} + results := violation with input as inp count(results) == 1 } test_2_bad_cpu { - input := {"review": review([ctr("a", "1", "9", "1", "3"), ctr("b", "1", "8", "1", "2")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "9", "1", "3"), ctr("b", "1", "8", "1", "2")]), "parameters": {"ratio": "2"}} + results := violation with input as inp count(results) == 2 } test_1_bad_ram { - input := {"review": review([ctr("a", "1", "2", "1" ,"2"), ctr("b", "8", "2", "2", "2")]), "parameters": {"ratio": "1"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1" ,"2"), ctr("b", "8", "2", "2", "2")]), "parameters": {"ratio": "1"}} + results := violation with input as inp count(results) == 1 } test_2_bad_ram { - input := {"review": review([ctr("a", "9", "2", "3", "2"), ctr("b", "8", "2", "2", "2")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "9", "2", "3", "2"), ctr("b", "8", "2", "2", "2")]), "parameters": {"ratio": "2"}} + results := violation with input as inp count(results) == 2 } test_no_ram_limit { - input := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"ratio": "4"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_no_cpu_limit { - input := {"review": review([{"name": "a", "resources": {"limits": {"memory": 1}}}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"limits": {"memory": 1}}}]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 2 } test_no_limit { - input := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 2 } test_no_ram_request { - input := {"review": review([{"name": "a", "resources": {"requests": {"cpu": 1}}}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"requests": {"cpu": 1}}}]), "parameters": {"ratio": "4"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_no_cpu_request { - input := {"review": review([{"name": "a", "resources": {"requests": {"memory": 1}}}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"requests": {"memory": 1}}}]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 2 } test_no_resources { - input := {"review": review([{"name": "a"}]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([{"name": "a"}]), "parameters": {"ratio": "4"}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_init_containers_checked { - input := {"review": init_review([ctr("a", "5", "5", "1", "1"), ctr("b", "5", "5", "1", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": init_review([ctr("a", "5", "5", "1", "1"), ctr("b", "5", "5", "1", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 4 } # MEM SCALE TESTS test_input_no_violations_mem_K { - input := {"review": review([ctr("a", "1k", "2", "1k", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1k", "2", "1k", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 0 } test_input_violations_mem_K { - input := {"review": review([ctr("a", "4k", "2", "1k", "2")]), "parameters": {"ratio": "2"}} - results := violation with input as input + inp := {"review": review([ctr("a", "4k", "2", "1k", "2")]), "parameters": {"ratio": "2"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_m { - input := {"review": review([ctr("a", "1", "2", "1m", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1", "2", "1m", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_M { - input := {"review": review([ctr("a", "1M", "2", "1k", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1M", "2", "1k", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_G { - input := {"review": review([ctr("a", "1G", "2", "1M", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1G", "2", "1M", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_T { - input := {"review": review([ctr("a", "1T", "2", "1G", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1T", "2", "1G", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_P { - input := {"review": review([ctr("a", "1P", "2", "1T", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1P", "2", "1T", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_E { - input := {"review": review([ctr("a", "1E", "2", "1P", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1E", "2", "1P", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ki { - input := {"review": review([ctr("a", "1Ki", "2", "1", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ki", "2", "1", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Mi { - input := {"review": review([ctr("a", "1Mi", "2", "1Ki", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Mi", "2", "1Ki", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Gi { - input := {"review": review([ctr("a", "1Gi", "2", "1Mi", "2")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi", "2", "1Mi", "2")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ti { - input := {"review": review([ctr("a", "1Ti", "2", "1Gi", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ti", "2", "1Gi", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Pi { - input := {"review": review([ctr("a", "1Pi", "2", "1Ti", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Pi", "2", "1Ti", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei { - input := {"review": review([ctr("a", "1Ei", "2", "1Pi", "1")]), "parameters": {"ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2", "1Pi", "1")]), "parameters": {"ratio": "4"}} + results := violation with input as inp count(results) == 1 } test_input_violations_mem_Ei_with_exemption { - input := {"review": review([ctr("a", "1Ei", "2", "1Pi", "1")]), "parameters": {"exemptImages": ["nginx"], "ratio": "4"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei", "2", "1Pi", "1")]), "parameters": {"exemptImages": ["nginx"], "ratio": "4"}} + results := violation with input as inp count(results) == 0 } ## cpuRatio tests test_input_no_violations_int_cpu_ratio_1 { - input := {"review": review([ctr("a", 5, 10, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 1}} - results := violation with input as input + inp := {"review": review([ctr("a", 5, 10, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 1}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_violations_int_cpu_ratio_1 { - input := {"review": review([ctr("a", 30, 15, 5, 10)]), "parameters": {"ratio": 10, "cpuRatio": 1}} - results := violation with input as input + inp := {"review": review([ctr("a", 30, 15, 5, 10)]), "parameters": {"ratio": 10, "cpuRatio": 1}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_input_no_violation_int_cpu_ratio_2 { - input := {"review": review([ctr("a", 5, 20, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 2}} - results := violation with input as input + inp := {"review": review([ctr("a", 5, 20, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 2}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_input_violation_int_cpu_ratio_2 { - input := {"review": review([ctr("a", 5, 21, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 2}} - results := violation with input as input + inp := {"review": review([ctr("a", 5, 21, 5, 10)]), "parameters": {"ratio": 1, "cpuRatio": 2}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_input_violation_int_cpu_ratio_2_with_exemption { - input := {"review": review([ctr("a", 5, 21, 5, 10)]), "parameters": {"exemptImages": ["nginx"], "ratio": 1, "cpuRatio": 2}} - results := violation with input as input + inp := {"review": review([ctr("a", 5, 21, 5, 10)]), "parameters": {"exemptImages": ["nginx"], "ratio": 1, "cpuRatio": 2}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } diff --git a/src/general/containerresources/src_test.rego b/src/general/containerresources/src_test.rego index 16191f335..355cb7b7a 100644 --- a/src/general/containerresources/src_test.rego +++ b/src/general/containerresources/src_test.rego @@ -2,259 +2,259 @@ package k8srequiredresources # "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]} test_without_resources_violations { - input := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_requests_cpu_violations { - input := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_requests_memory_violations { - input := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_requests_violations { - input := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_limits_cpu_violations { - input := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_limits_memory_violations { - input := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_limits_violations { - input := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_with_resources_no_violations { - input := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } # "parameters": {"limits": ["memory"], "requests": ["cpu"]} test_without_resources_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_requests_cpu_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_requests_memory_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_requests_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_limits_cpu_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 2 } test_limits_memory_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_limits_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_with_resources_with_empty_requests_memory_no_violations { - input := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["memory"], "requests": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } # "parameters": {"limits": ["cpu"]} test_without_resources_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_requests_cpu_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_requests_memory_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_requests_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_limits_cpu_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_limits_memory_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 1 } test_limits_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_with_resources_with_empty_requests_and_limits_memory_no_violations { - input := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["cpu"]}} - results := violation with input as input + inp := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": ["cpu"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } # "parameters": {"limits": [], "requests": []} test_without_resources_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_without_resources("test")]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_requests_cpu_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_requests_cpu("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_requests_memory_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_requests_memory("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_requests_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_requests("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_limits_cpu_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_limits_cpu("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_limits_memory_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_limits_memory("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_limits_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_limits("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_with_resources_with_empty_limits_and_requests_no_violations { - input := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": [], "requests": []}} - results := violation with input as input + inp := {"review": review([ctr_with_resources("test", 1)]), "parameters": {"limits": [], "requests": []}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } # multiple containers, "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]} test_multiple_without_resources_violations { - input := {"review": review([ctr_without_resources("test1"),ctr_without_resources("test2"),ctr_without_resources("test3")]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_without_resources("test1"),ctr_without_resources("test2"),ctr_without_resources("test3")]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 6 } test_multiple_with_resources_no_violations { - input := {"review": review([ctr_with_resources("test1", 1),ctr_with_resources("test2", 2),ctr_with_resources("test3", 3)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} - results := violation with input as input + inp := {"review": review([ctr_with_resources("test1", 1),ctr_with_resources("test2", 2),ctr_with_resources("test3", 3)]), "parameters": {"limits": ["cpu", "memory"], "requests": ["cpu", "memory"]}} + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } # multiple containers test_multiple_with_init_violations_1 { - input := { + inp := { "review": review_with_init( [ - ctr_without_resources("test1"), - ctr_with_resources("test2", 2), + ctr_without_resources("test1"), + ctr_with_resources("test2", 2), ctr_limits_memory("test3", 3) ], [ - ctr_requests("test4", 1), - ctr_requests_memory("test5", 2), + ctr_requests("test4", 1), + ctr_requests_memory("test5", 2), ctr_limits_cpu("test6", 3) ] ), @@ -265,21 +265,21 @@ test_multiple_with_init_violations_1 { ] } } - results := violation with input as input + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 4 } test_multiple_with_init_no_violations { - input := { + inp := { "review": review_with_init( [ - ctr_with_resources("test1", 1), - ctr_requests("test2", 2), + ctr_with_resources("test1", 1), + ctr_requests("test2", 2), ], [ - ctr_with_resources("test3", 1), - ctr_requests("test4", 2), + ctr_with_resources("test3", 1), + ctr_requests("test4", 2), ] ), "parameters": { @@ -289,22 +289,22 @@ test_multiple_with_init_no_violations { ] } } - results := violation with input as input + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 0 } test_multiple_with_init_violations_2 { - input := { + inp := { "review": review_with_init( [ - ctr_without_resources("test1"), - ctr_limits_memory("test2", 2), + ctr_without_resources("test1"), + ctr_limits_memory("test2", 2), ctr_limits("test3", 3) ], [ - ctr_requests_cpu("test4", 1), - ctr_with_resources("test5", 2), + ctr_requests_cpu("test4", 1), + ctr_with_resources("test5", 2), ctr_limits_cpu("test6", 3) ] ), @@ -318,7 +318,7 @@ test_multiple_with_init_violations_2 { ] } } - results := violation with input as input + results := violation with input as inp trace(sprintf("results - <%v>", [results])) count(results) == 8 } diff --git a/src/general/disallowanonymous/src_test.rego b/src/general/disallowanonymous/src_test.rego index a4d5d2089..6a6c5759f 100644 --- a/src/general/disallowanonymous/src_test.rego +++ b/src/general/disallowanonymous/src_test.rego @@ -1,224 +1,224 @@ package k8sdisallowanonymous test_blank_subject_clusterrolebinding { - input := {"review": clusterrolebinding([{}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 0 } test_authenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 0 } test_non_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "user-1", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "user-1", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 0 } test_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_anonymous_user_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } test_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_unauthenticated_group_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_mix_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_mix_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_mix_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_mix_clusterrolebinding { - input := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": clusterrolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } test_blank_subject_rolebinding { - input := {"review": rolebinding([{}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 0 } test_non_anonymous_rolebinding { - input := {"review": rolebinding([{"name": "user-1", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "user-1", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 0 } test_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_anonymous_user_rolebinding { - input := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:anonymous", "kind": "User"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } test_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_unauthenticated_group_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:authenticated", "kind": "Group"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_subjects_mix_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1"]}} + results := violation with input as inp count(results) == 1 } test_allowed_role_multiple_subjects_mix_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-2"]}} + results := violation with input as inp count(results) == 0 } test_multiple_role_multiple_subjects_mix_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-3"]}} + results := violation with input as inp count(results) == 1 } test_allowed_multiple_role_multiple_subjects_mix_rolebinding { - input := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} - results := violation with input as input + inp := {"review": rolebinding([{"name": "system:unauthenticated", "kind": "Group"}, {"name": "system:anonymous", "kind": "User"}], "role-2"), "parameters": {"allowedRoles": ["role-1", "role-2"]}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/disallowedrepos/src_test.rego b/src/general/disallowedrepos/src_test.rego index d13458af8..b05d7e62e 100644 --- a/src/general/disallowedrepos/src_test.rego +++ b/src/general/disallowedrepos/src_test.rego @@ -1,75 +1,75 @@ package k8sdisallowedrepos test_input_allowed_container { - input := { "review": input_review(input_container_allowed), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_allowed), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_container_x2 { - input := { "review": input_review(input_container_allowed), "parameters": {"repos": ["other", "disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_allowed), "parameters": {"repos": ["other", "disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_container { - input := { "review": input_review(input_container_dual_allowed), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_dual_allowed), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_container { - input := { "review": input_review(input_container_denied), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_x2 { - input := { "review": input_review(input_container_denied), "parameters": {"repos": ["other", "disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied), "parameters": {"repos": ["other", "disallowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container { - input := { "review": input_review(input_container_dual_denied), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_review(input_container_dual_denied), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 1 } # init containers test_input_allowed_initcontainer { - input := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_initcontainer_x2 { - input := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["other", "disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed), "parameters": {"repos": ["other", "disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_initcontainer { - input := { "review": input_init_review(input_container_dual_allowed), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_allowed), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_initcontainer { - input := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_initcontainer_x2 { - input := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["other", "disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied), "parameters": {"repos": ["other", "disallowed"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_initcontainer { - input := { "review": input_init_review(input_container_dual_denied), "parameters": {"repos": ["disallowed"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_denied), "parameters": {"repos": ["disallowed"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_initcontainer { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"repos": ["allowed"]}} + results := violation with input as inp count(results) == 1 } diff --git a/src/general/disallowedtags/constraint.tmpl b/src/general/disallowedtags/constraint.tmpl index 4e803e6e7..561d55206 100644 --- a/src/general/disallowedtags/constraint.tmpl +++ b/src/general/disallowedtags/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8sdisallowedtags annotations: metadata.gatekeeper.sh/title: "Disallow tags" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to have an image tag different from the ones in the specified list. diff --git a/src/general/disallowedtags/src.rego b/src/general/disallowedtags/src.rego index d35964fd7..de10aeb7e 100644 --- a/src/general/disallowedtags/src.rego +++ b/src/general/disallowedtags/src.rego @@ -5,16 +5,15 @@ import data.lib.exempt_container.is_exempt violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tags := [forbid | tag = input.parameters.tags[_] ; forbid = endswith(container.image, concat(":", ["", tag]))] - any(tags) + tags := [tag_with_prefix | tag := input.parameters.tags[_]; tag_with_prefix := concat(":", ["", tag])] + strings.any_suffix_match(container.image, tags) msg := sprintf("container <%v> uses a disallowed tag <%v>; disallowed tags are %v", [container.name, container.image, input.parameters.tags]) } violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tag := [contains(container.image, ":")] - not all(tag) + not contains(container.image, ":") msg := sprintf("container <%v> didn't specify an image tag <%v>", [container.name, container.image]) } diff --git a/src/general/disallowedtags/src_test.rego b/src/general/disallowedtags/src_test.rego index 71a8805b7..7bddec15f 100644 --- a/src/general/disallowedtags/src_test.rego +++ b/src/general/disallowedtags/src_test.rego @@ -1,110 +1,110 @@ package k8sdisallowedtags test_input_allowed_container { - input := { "review": input_review(input_container_allowed), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(input_container_allowed), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_container { - input := { "review": input_review(input_container_dual_allowed), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(input_container_dual_allowed), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_container_emtpy { - input := { "review": input_review(input_container_denied_empty), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied_empty), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_latest { - input := { "review": input_review(input_container_denied_latest), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied_latest), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_testing { - input := { "review": input_review(input_container_denied_testing), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(input_container_denied_testing), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container_empty_tag { - input := { "review": input_review(array.concat(input_container_denied_empty, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_denied_empty, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_dual_container_2tags { - input := { "review": input_review(array.concat(input_container_denied_testing, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_denied_testing, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container_empty { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied_empty)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied_empty)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_mixed_container_latest { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } # init containers test_input_allowed_container { - input := { "review": input_init_review(input_container_allowed), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 0 } test_input_allowed_dual_container { - input := { "review": input_init_review(input_container_dual_allowed), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_allowed), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 0 } test_input_denied_container_emtpy { - input := { "review": input_init_review(input_container_denied_empty), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied_empty), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_latest { - input := { "review": input_init_review(input_container_denied_latest), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied_latest), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_container_testing { - input := { "review": input_init_review(input_container_denied_testing), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_denied_testing), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container_empty_tag { - input := { "review": input_init_review(array.concat(input_container_denied_empty, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_denied_empty, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_dual_container_2tags { - input := { "review": input_init_review(array.concat(input_container_denied_testing, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_denied_testing, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container_empty { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied_empty)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied_empty)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_mixed_container_latest { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"]}} + results := violation with input as inp count(results) == 1 } test_input_denied_mixed_container_with_some_exempt_image { - input := { "review": input_init_review(array.concat(input_container_exempt, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_exempt, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest"]}} + results := violation with input as inp count(results) == 2 } test_input_denied_dual_container_with_all_exempt_image { - input := { "review": input_init_review(array.concat(input_container_exempt, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest", "exempt:testing"]}} - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_exempt, input_container_denied_latest)), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest", "exempt:testing"]}} + results := violation with input as inp count(results) == 1 } test_input_allowed_dual_container_with_exempt_image { - input := { "review": input_init_review(input_container_exempt), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest", "exempt:testing"]}} - results := violation with input as input + inp := { "review": input_init_review(input_container_exempt), "parameters": {"tags": ["latest", "testing"], "exemptImages": ["exempt:latest", "exempt:testing"]}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/disallowinteractive/src_test.rego b/src/general/disallowinteractive/src_test.rego index 78af2ca2d..5a408ae3d 100644 --- a/src/general/disallowinteractive/src_test.rego +++ b/src/general/disallowinteractive/src_test.rego @@ -1,48 +1,48 @@ package k8sdisallowinteractivetty test_input_container_not_tty_allowed { - input := { "review": input_review} - results := violation with input as input + inp := {"review": input_review} + results := violation with input as inp count(results) == 0 } test_input_container_stdin_not_allowed { - input := { "review": input_review_stdin} - results := violation with input as input + inp:= {"review": input_review_stdin} + results := violation with input as inp count(results) == 1 } test_input_container_tty_not_allowed { - input := { "review": input_review_tty} - results := violation with input as input + inp := {"review": input_review_tty} + results := violation with input as inp count(results) == 1 } test_input_one_container_with_exemption { - input := { "review": input_review_stdin, "parameters": {"exemptImages": ["one/*"]}} - results := violation with input as input + inp := {"review": input_review_stdin, "parameters": {"exemptImages": ["one/*"]}} + results := violation with input as inp count(results) == 0 } test_input_container_many_not_stdin_allowed { - input := { "review": input_review_many} - results := violation with input as input + inp := {"review": input_review_many} + results := violation with input as inp count(results) == 1 } test_input_container_many_mixed_stdin_not_allowed { - input := { "review": input_review_many_mixed} - results := violation with input as input + inp := {"review": input_review_many_mixed} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_stdin_not_allowed_one_exempted { - input := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*"]}} - results := violation with input as input + inp := {"review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*"]}} + results := violation with input as inp count(results) == 1 } test_input_container_many_mixed_stdin_not_allowed_all_exempted { - input := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*", "two/*", "three/*"]}} - results := violation with input as input + inp := {"review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*", "two/*", "three/*"]}} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_stdin_not_allowed_two { - input := { "review": input_review_many_mixed_two} - results := violation with input as input + inp := {"review": input_review_many_mixed_two} + results := violation with input as inp count(results) == 2 } @@ -149,7 +149,7 @@ input_containers_many = [ "name": "nginx2", "image": "three/nginx", "stdin": true - + }] input_containers_many_mixed = [ diff --git a/src/general/ephemeralstoragelimit/constraint.tmpl b/src/general/ephemeralstoragelimit/constraint.tmpl index 827b6bd52..488f8a47d 100644 --- a/src/general/ephemeralstoragelimit/constraint.tmpl +++ b/src/general/ephemeralstoragelimit/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8scontainerephemeralstoragelimit annotations: metadata.gatekeeper.sh/title: "Container ephemeral storage limit" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires containers to have an ephemeral storage limit set and constrains the limit to be within the specified maximum values. diff --git a/src/general/ephemeralstoragelimit/src.rego b/src/general/ephemeralstoragelimit/src.rego index 88100fbf5..f7951ca66 100644 --- a/src/general/ephemeralstoragelimit/src.rego +++ b/src/general/ephemeralstoragelimit/src.rego @@ -108,7 +108,7 @@ canonify_storage(orig) = new { not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * storage_multiple(suffix) } diff --git a/src/general/ephemeralstoragelimit/src_test.rego b/src/general/ephemeralstoragelimit/src_test.rego index c2ede0c4d..fa3d60ac9 100644 --- a/src/general/ephemeralstoragelimit/src_test.rego +++ b/src/general/ephemeralstoragelimit/src_test.rego @@ -1,155 +1,155 @@ package k8scontainerephemeralstoragelimit test_input_no_violations_int { - input := {"review": review([ctr("a", 4096)]), "parameters": {"ephemeral-storage": "8192"}} - results := violation with input as input + inp := {"review": review([ctr("a", 4096)]), "parameters": {"ephemeral-storage": "8192"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str { - input := {"review": review([ctr("a", "1Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_str_small { - input := {"review": review([ctr("a", "100")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "100")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 0 } test_input_violations_int { - input := {"review": review([ctr("a", 4096)]), "parameters": {"ephemeral-storage": "2048"}} - results := violation with input as input + inp := {"review": review([ctr("a", 4096)]), "parameters": {"ephemeral-storage": "2048"}} + results := violation with input as inp count(results) == 1 } test_input_violations_str { - input := {"review": review([ctr("a", "2.5Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "2.5Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_str_small { - input := {"review": review([ctr("a", "130")]), "parameters": {"ephemeral-storage": 128}} - results := violation with input as input + inp := {"review": review([ctr("a", "130")]), "parameters": {"ephemeral-storage": 128}} + results := violation with input as inp count(results) == 1 } test_no_parse_ephemeral_storage { - input := {"review": review([ctr("a", "123def")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "123def")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_1_bad_eph { - input := {"review": review([ctr("a", "1Gi"), ctr("a", "3Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi"), ctr("a", "3Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_2_bad_eph { - input := {"review": review([ctr("a", "2.5Gi"), ctr("a", "3Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "2.5Gi"), ctr("a", "3Gi")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 2 } test_no_eph_limit { - input := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {"limits": {"cpu": 1}}}]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_no_limit { - input := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([{"name": "a", "resources": {}}]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_no_resources { - input := {"review": review([{"name": "a"}]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([{"name": "a"}]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_init_containers_checked { - input := {"review": init_review([ctr("a", "2.2 Ti")]), "parameters": {"ephemeral-storage": "3Gi"}} - results := violation with input as input + inp := {"review": init_review([ctr("a", "2.2 Ti")]), "parameters": {"ephemeral-storage": "3Gi"}} + results := violation with input as inp count(results) == 1 } # # EPH SCALE TESTS test_input_no_violations_eph_k { - input := {"review": review([ctr("a", "100k")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "100k")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 0 } test_input_violations_eph_m { - input := {"review": review([ctr("a", "10000m")]), "parameters": {"ephemeral-storage": "9"}} - results := violation with input as input + inp := {"review": review([ctr("a", "10000m")]), "parameters": {"ephemeral-storage": "9"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_K { - input := {"review": review([ctr("a", "1k")]), "parameters": {"ephemeral-storage": "999"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1k")]), "parameters": {"ephemeral-storage": "999"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_M { - input := {"review": review([ctr("a", "1M")]), "parameters": {"ephemeral-storage": 999999}} - results := violation with input as input + inp := {"review": review([ctr("a", "1M")]), "parameters": {"ephemeral-storage": 999999}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_G { - input := {"review": review([ctr("a", "1G")]), "parameters": {"ephemeral-storage": "999999999"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1G")]), "parameters": {"ephemeral-storage": "999999999"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_T { - input := {"review": review([ctr("a", "1T")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1T")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_P { - input := {"review": review([ctr("a", "1P")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1P")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_E { - input := {"review": review([ctr("a", "1E")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1E")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Ki { - input := {"review": review([ctr("a", "1Ki")]), "parameters": {"ephemeral-storage": "1023"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ki")]), "parameters": {"ephemeral-storage": "1023"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Mi { - input := {"review": review([ctr("a", "1Mi")]), "parameters": {"ephemeral-storage": "0.5Mi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Mi")]), "parameters": {"ephemeral-storage": "0.5Mi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Gi { - input := {"review": review([ctr("a", "1Gi")]), "parameters": {"ephemeral-storage": "0.22Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Gi")]), "parameters": {"ephemeral-storage": "0.22Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_decimal_eph_Gi { - input := {"review": review([ctr("a", "1.4Gi")]), "parameters": {"ephemeral-storage": "1Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1.4Gi")]), "parameters": {"ephemeral-storage": "1Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Ti { - input := {"review": review([ctr("a", "1Ti")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ti")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Pi { - input := {"review": review([ctr("a", "1Pi")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Pi")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Ei { - input := {"review": review([ctr("a", "1Ei")]), "parameters": {"ephemeral-storage": "2Gi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei")]), "parameters": {"ephemeral-storage": "2Gi"}} + results := violation with input as inp count(results) == 1 } test_input_violations_eph_Ei_with_exemption { - input := {"review": review([ctr("a", "1Ei")]), "parameters": {"exemptImages": ["nginx"], "ephemeral-storage": "1Pi"}} - results := violation with input as input + inp := {"review": review([ctr("a", "1Ei")]), "parameters": {"exemptImages": ["nginx"], "ephemeral-storage": "1Pi"}} + results := violation with input as inp count(results) == 0 } test_update { - input := {"review": object.union(review([ctr("a", 4096)]), {"operation": "UPDATE"}), "parameters": {"ephemeral-storage": "2048"}} - results := violation with input as input + inp := {"review": object.union(review([ctr("a", 4096)]), {"operation": "UPDATE"}), "parameters": {"ephemeral-storage": "2048"}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/externalip/src_test.rego b/src/general/externalip/src_test.rego index 6f2211b17..f5e050afe 100644 --- a/src/general/externalip/src_test.rego +++ b/src/general/externalip/src_test.rego @@ -1,49 +1,49 @@ package k8sexternalips test_input_non_svc { - input := {"review": non_svc, "parameters": {"allowedIPs": ["1.2.3.4"]}} - results := violation with input as input + inp := {"review": non_svc, "parameters": {"allowedIPs": ["1.2.3.4"]}} + results := violation with input as inp count(results) == 0 } test_input_no_external_ip { - input := {"review": non_externalip_svc, "parameters": {"allowedIPs": ["1.2.3.4"]}} - results := violation with input as input + inp := {"review": non_externalip_svc, "parameters": {"allowedIPs": ["1.2.3.4"]}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_externalip { - input := {"review": externalip_svc(["1.2.3.4"]), "parameters": {"allowedIPs": ["1.2.3.4"]}} - results := violation with input as input + inp := {"review": externalip_svc(["1.2.3.4"]), "parameters": {"allowedIPs": ["1.2.3.4"]}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_externalip_multiple { - input := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "203.0.113.0", "1.2.3.4", "203.0.113.1"]}} - results := violation with input as input + inp := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "203.0.113.0", "1.2.3.4", "203.0.113.1"]}} + results := violation with input as inp count(results) == 0 } test_input_no_violations_empty { - input := {"review": externalip_svc([]), "parameters": {"allowedIPs": []}} - results := violation with input as input + inp := {"review": externalip_svc([]), "parameters": {"allowedIPs": []}} + results := violation with input as inp count(results) == 0 } test_input_violations_externalip { - input := {"review": externalip_svc(["203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "1.2.3.4"]}} - results := violation with input as input + inp := {"review": externalip_svc(["203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "1.2.3.4"]}} + results := violation with input as inp results count(results) == 1 } test_input_violations_none_allowed { - input := {"review": externalip_svc(["203.0.113.0"]), "parameters": {"allowedIPs": []}} - results := violation with input as input + inp := {"review": externalip_svc(["203.0.113.0"]), "parameters": {"allowedIPs": []}} + results := violation with input as inp count(results) == 1 } test_input_violations_partial { - input := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "1.2.3.4", "203.0.113.1"]}} - results := violation with input as input + inp := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "1.2.3.4", "203.0.113.1"]}} + results := violation with input as inp count(results) == 1 } test_input_violations_multiple { - input := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "203.0.113.1"]}} - results := violation with input as input + inp := {"review": externalip_svc(["1.2.3.4", "203.0.113.0"]), "parameters": {"allowedIPs": ["1.1.1.1", "203.0.113.1"]}} + results := violation with input as inp count(results) == 1 # Multiple failing IPs reported in single error message. } diff --git a/src/general/horizontalpodautoscaler/src_test.rego b/src/general/horizontalpodautoscaler/src_test.rego index 4100ab8db..6822cd787 100644 --- a/src/general/horizontalpodautoscaler/src_test.rego +++ b/src/general/horizontalpodautoscaler/src_test.rego @@ -2,7 +2,7 @@ package k8shorizontalpodautoscaler namespace := "namespace-1" -valid_scale_target_ref := { +valid_scale_target_ref := { "apiVersion": "apps/v1", "kind": "Deployment", "name": "deployment-1" @@ -27,58 +27,58 @@ deployment := { } test_input_hpa_min_replicas_outside_range { - input := {"review": input_hpa(2,5,valid_scale_target_ref), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := {"review": input_hpa(2,5,valid_scale_target_ref), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 1 } test_input_hpa_max_replicas_outside_range { - input := {"review": input_hpa(4,7,valid_scale_target_ref), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := {"review": input_hpa(4,7,valid_scale_target_ref), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 1 } test_input_hpa_replicas_within_range { - input := {"review": input_hpa(4,5,valid_scale_target_ref), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := {"review": input_hpa(4,5,valid_scale_target_ref), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 0 } test_input_hpa_replicas_equal_range { - input := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 0 } test_input_hpa_replicas_below_min_spread { - input := {"review": input_hpa(3,4,valid_scale_target_ref), "parameters": input_parameters_min_spread} - results := violation with input as input + inp := {"review": input_hpa(3,4,valid_scale_target_ref), "parameters": input_parameters_min_spread} + results := violation with input as inp count(results) == 1 } test_input_hpa_replicas_above_min_spread { - input := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_min_spread} - results := violation with input as input + inp := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_min_spread} + results := violation with input as inp count(results) == 0 } test_input_hpa_replicas_equal_min_spread { - input := {"review": input_hpa(4,6,valid_scale_target_ref), "parameters": input_parameters_min_spread} - results := violation with input as input + inp := {"review": input_hpa(4,6,valid_scale_target_ref), "parameters": input_parameters_min_spread} + results := violation with input as inp count(results) == 0 } test_input_hpa_invalid_scale_target{ - input := {"review": input_hpa(3,6,invalid_scale_target_ref), "parameters": input_parameters_enforce_scale_target_ref} + inp := {"review": input_hpa(3,6,invalid_scale_target_ref), "parameters": input_parameters_enforce_scale_target_ref} inv := inv_deployment(deployment) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_hpa_valid_scale_target{ - input := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_enforce_scale_target_ref} + inp := {"review": input_hpa(3,6,valid_scale_target_ref), "parameters": input_parameters_enforce_scale_target_ref} inv := inv_deployment(deployment) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } diff --git a/src/general/httpsonly/constraint.tmpl b/src/general/httpsonly/constraint.tmpl index 1ce8621e9..5eff2a7c4 100644 --- a/src/general/httpsonly/constraint.tmpl +++ b/src/general/httpsonly/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8shttpsonly annotations: metadata.gatekeeper.sh/title: "HTTPS Only" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires Ingress resources to be HTTPS only. Ingress resources must include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. diff --git a/src/general/httpsonly/src.rego b/src/general/httpsonly/src.rego index 0661b6e15..b6b58b298 100644 --- a/src/general/httpsonly/src.rego +++ b/src/general/httpsonly/src.rego @@ -2,19 +2,19 @@ package k8shttpsonly violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not https_complete(ingress) - not tls_is_optional(ingress) + not tls_is_optional msg := sprintf("Ingress should be https. tls configuration and allow-http=false annotation are required for %v", [ingress.metadata.name]) } violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not annotation_complete(ingress) - not tls_not_optional(ingress) + tls_is_optional msg := sprintf("Ingress should be https. The allow-http=false annotation is required for %v", [ingress.metadata.name]) } @@ -28,15 +28,7 @@ annotation_complete(ingress) = true { ingress.metadata.annotations["kubernetes.io/ingress.allow-http"] == "false" } -tls_is_optional(ingress) = true { +tls_is_optional { parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - is_boolean(tlsOptional) - true == tlsOptional -} - -tls_not_optional(ingress) = true { - parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - true != tlsOptional + object.get(parameters, "tlsOptional", false) == true } diff --git a/src/general/httpsonly/src_test.rego b/src/general/httpsonly/src_test.rego index 498480243..0c3cf3878 100644 --- a/src/general/httpsonly/src_test.rego +++ b/src/general/httpsonly/src_test.rego @@ -1,63 +1,63 @@ package k8shttpsonly test_http_disallowed { - input := {"review": review_ingress(annotation("false"), tls)} - results := violation with input as input + inp := {"review": review_ingress(annotation("false"), tls)} + results := violation with input as inp count(results) == 0 } test_boolean_annotation { - input := {"review": review_ingress(annotation(false), tls)} - results := violation with input as input + inp := {"review": review_ingress(annotation(false), tls)} + results := violation with input as inp count(results) == 1 } test_true_annotation { - input := {"review": review_ingress(annotation("true"), tls)} - results := violation with input as input + inp := {"review": review_ingress(annotation("true"), tls)} + results := violation with input as inp count(results) == 1 } test_missing_annotation { - input := {"review": review_ingress({}, tls)} - results := violation with input as input + inp := {"review": review_ingress({}, tls)} + results := violation with input as inp count(results) == 1 } test_empty_tls { - input := {"review": review_ingress({}, empty_tls)} - results := violation with input as input + inp := {"review": review_ingress({}, empty_tls)} + results := violation with input as inp count(results) == 1 } test_missing_tls { - input := {"review": review_ingress(annotation("false"), {})} - results := violation with input as input + inp := {"review": review_ingress(annotation("false"), {})} + results := violation with input as inp count(results) == 1 } test_missing_all { - input := {"review": review_ingress({}, {})} - results := violation with input as input + inp := {"review": review_ingress({}, {})} + results := violation with input as inp count(results) == 1 } test_tls_optional_missing_tls { - input := {"review": review_ingress(annotation("false"), {}), "parameters": {"tlsOptional": true}} - results := violation with input as input + inp := {"review": review_ingress(annotation("false"), {}), "parameters": {"tlsOptional": true}} + results := violation with input as inp count(results) == 0 } test_tls_optional_empty_tls { - input := {"review": review_ingress(annotation("false"), empty_tls), "parameters": {"tlsOptional": true}} - results := violation with input as input + inp := {"review": review_ingress(annotation("false"), empty_tls), "parameters": {"tlsOptional": true}} + results := violation with input as inp count(results) == 0 } test_tls_optional_with_tls { - input := {"review": review_ingress(annotation("false"), tls), "parameters": {"tlsOptional": true}} - results := violation with input as input + inp := {"review": review_ingress(annotation("false"), tls), "parameters": {"tlsOptional": true}} + results := violation with input as inp count(results) == 0 } test_tls_optional_true_annotation { - input := {"review": review_ingress(annotation("true"), {}), "parameters": {"tlsOptional": true}} - results := violation with input as input + inp := {"review": review_ingress(annotation("true"), {}), "parameters": {"tlsOptional": true}} + results := violation with input as inp count(results) == 1 } test_tls_optional_missing_annotation { - input := {"review": review_ingress({}, {}), "parameters": {"tlsOptional": true}} - results := violation with input as input + inp := {"review": review_ingress({}, {}), "parameters": {"tlsOptional": true}} + results := violation with input as inp count(results) == 1 } diff --git a/src/general/imagedigests/constraint.tmpl b/src/general/imagedigests/constraint.tmpl index df49d9146..2b9193c62 100644 --- a/src/general/imagedigests/constraint.tmpl +++ b/src/general/imagedigests/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8simagedigests annotations: metadata.gatekeeper.sh/title: "Image Digests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to contain a digest. diff --git a/src/general/imagedigests/src.rego b/src/general/imagedigests/src.rego index a1fdd3836..0170f8c04 100644 --- a/src/general/imagedigests/src.rego +++ b/src/general/imagedigests/src.rego @@ -5,23 +5,20 @@ import data.lib.exempt_container.is_exempt violation[{"msg": msg}] { container := input.review.object.spec.containers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } diff --git a/src/general/imagedigests/src_test.rego b/src/general/imagedigests/src_test.rego index 7023bb478..140845157 100644 --- a/src/general/imagedigests/src_test.rego +++ b/src/general/imagedigests/src_test.rego @@ -1,85 +1,85 @@ package k8simagedigests test_input_allowed_container { - input := { "review": input_review(input_container_allowed) } - results := violation with input as input + inp := { "review": input_review(input_container_allowed) } + results := violation with input as inp count(results) == 0 } test_input_allowed_container_with_tag_and_digest { - input := { "review": input_review(input_container_allowed_with_tag) } - results := violation with input as input + inp := { "review": input_review(input_container_allowed_with_tag) } + results := violation with input as inp count(results) == 0 } test_input_allowed_containers_with_registered_algorithms { - input := { "review": input_review(input_container_allowed_registered_algorithms) } - results := violation with input as input + inp := { "review": input_review(input_container_allowed_registered_algorithms) } + results := violation with input as inp count(results) == 0 } test_input_allowed_containers_with_unregistered_algorithms { - input := { "review": input_review(input_container_allowed_unregistered_algorithms) } - results := violation with input as input + inp := { "review": input_review(input_container_allowed_unregistered_algorithms) } + results := violation with input as inp count(results) == 0 } test_input_denied_container { - input := { "review": input_review(input_container_denied) } - results := violation with input as input + inp := { "review": input_review(input_container_denied) } + results := violation with input as inp count(results) == 1 } test_input_denied_dual_container { - input := { "review": input_review(input_container_dual_denied) } - results := violation with input as input + inp := { "review": input_review(input_container_dual_denied) } + results := violation with input as inp count(results) == 2 } test_input_denied_mixed_container { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied)) } - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied)) } + results := violation with input as inp count(results) == 1 } test_input_denied_mixed_container_with_exemption { - input := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"exemptImages": ["denied/*"]} } - results := violation with input as input + inp := { "review": input_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"exemptImages": ["denied/*"]} } + results := violation with input as inp count(results) == 0 } # init containers test_input_init_allowed_container { - input := { "review": input_init_review(input_container_allowed) } - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed) } + results := violation with input as inp count(results) == 0 } test_input_init_allowed_container_with_tag_and_digest { - input := { "review": input_init_review(input_container_allowed_with_tag) } - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed_with_tag) } + results := violation with input as inp count(results) == 0 } test_input_init_allowed_containers_with_registered_algorithms { - input := { "review": input_init_review(input_container_allowed_registered_algorithms) } - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed_registered_algorithms) } + results := violation with input as inp count(results) == 0 } test_input_init_allowed_containers_with_unregistered_algorithms { - input := { "review": input_init_review(input_container_allowed_unregistered_algorithms) } - results := violation with input as input + inp := { "review": input_init_review(input_container_allowed_unregistered_algorithms) } + results := violation with input as inp count(results) == 0 } test_input_init_denied_container { - input := { "review": input_init_review(input_container_denied) } - results := violation with input as input + inp := { "review": input_init_review(input_container_denied) } + results := violation with input as inp count(results) == 1 } test_input_init_denied_dual_container { - input := { "review": input_init_review(input_container_dual_denied) } - results := violation with input as input + inp := { "review": input_init_review(input_container_dual_denied) } + results := violation with input as inp count(results) == 2 } test_input_init_denied_mixed_container { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)) } - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)) } + results := violation with input as inp count(results) == 1 } test_input_init_denied_mixed_container_with_exemption { - input := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"exemptImages": ["denied/*"]} } - results := violation with input as input + inp := { "review": input_init_review(array.concat(input_container_allowed, input_container_denied)), "parameters": {"exemptImages": ["denied/*"]} } + results := violation with input as inp count(results) == 0 } diff --git a/src/general/noupdateserviceaccount/constraint.tmpl b/src/general/noupdateserviceaccount/constraint.tmpl index 58a2c17e3..fa25c9b02 100644 --- a/src/general/noupdateserviceaccount/constraint.tmpl +++ b/src/general/noupdateserviceaccount/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: noupdateserviceaccount annotations: metadata.gatekeeper.sh/title: "Block updating Service Account" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: "Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode." spec: crd: diff --git a/src/general/noupdateserviceaccount/src.rego b/src/general/noupdateserviceaccount/src.rego index 8ba2ae9ae..53f8cf321 100644 --- a/src/general/noupdateserviceaccount/src.rego +++ b/src/general/noupdateserviceaccount/src.rego @@ -1,12 +1,14 @@ package noupdateserviceaccount -privileged(userInfo, allowedUsers, allowedGroups) { +privileged(userInfo, allowedUsers, _) { # Allow if the user is in allowedUsers. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. username := object.get(userInfo, "username", "") allowedUsers[_] == username -} { +} + +privileged(userInfo, _, allowedGroups) { # Allow if the user's groups intersect allowedGroups. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. diff --git a/src/general/noupdateserviceaccount/src_test.rego b/src/general/noupdateserviceaccount/src_test.rego index 7b447a61b..11eb2a52a 100644 --- a/src/general/noupdateserviceaccount/src_test.rego +++ b/src/general/noupdateserviceaccount/src_test.rego @@ -15,11 +15,11 @@ pod(sa_name) = obj { } test_deny_pod { - input := { + inp := { "review": update(pod("sa1"), pod("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -37,11 +37,11 @@ rc(sa_name) = obj { } test_deny_rc { - input := { + inp := { "review": update(rc("sa1"), rc("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -59,11 +59,11 @@ rs(sa_name) = obj { } test_deny_rs { - input := { + inp := { "review": update(rs("sa1"), rs("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -81,11 +81,11 @@ deploy(sa_name) = obj { } test_deny_deploy { - input := { + inp := { "review": update(deploy("sa1"), deploy("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -103,11 +103,11 @@ ss(sa_name) = obj { } test_deny_ss { - input := { + inp := { "review": update(ss("sa1"), ss("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -125,11 +125,11 @@ ds(sa_name) = obj { } test_deny_ds { - input := { + inp := { "review": update(ds("sa1"), ds("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -147,11 +147,11 @@ job(sa_name) = obj { } test_deny_job { - input := { + inp := { "review": update(job("sa1"), job("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -173,11 +173,11 @@ cronjob(sa_name) = obj { } test_deny_cronjob { - input := { + inp := { "review": update(cronjob("sa1"), cronjob("sa2"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) result == policy_violation } @@ -196,74 +196,74 @@ test_allow_unrelated { } } } - input := { + inp := { "review": update(a, b, {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) count(result) == 0 } # Allow create and delete test_allow_create { - input := { + inp := { "review": create(deploy("sa1")), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) count(result) == 0 } test_allow_delete { - input := { + inp := { "review": delete(deploy("sa1")), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) count(result) == 0 } # Allowlist users and groups test_allow_users { - input := { + inp := { "review": update(deploy("sa1"), deploy("sa2"), {"username": "myuser"}), "parameters": allow(["myuser"], []), } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) count(result) == 0 } test_allow_groups { - input := { + inp := { "review": update(deploy("sa1"), deploy("sa2"), {"groups": ["mygroup"]}), "parameters": allow([], ["mygroup"]), } - result := violation with input as input + result := violation with input as inp trace(sprintf("result: %v", [result])) count(result) == 0 } # Malformed test_deny_missing_old { - input := { + inp := { "review": update({}, pod("sa"), {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("%v", [result])) result == missing_old_violation } test_deny_missing_new { - input := { + inp := { "review": update(pod("sa"), {}, {}), "parameters": {}, } - result := violation with input as input + result := violation with input as inp trace(sprintf("%v", [result])) result == missing_new_violation } diff --git a/src/general/poddisruptionbudget/src_test.rego b/src/general/poddisruptionbudget/src_test.rego index d45888eec..73f1327cf 100644 --- a/src/general/poddisruptionbudget/src_test.rego +++ b/src/general/poddisruptionbudget/src_test.rego @@ -8,42 +8,42 @@ match_labels := {"matchLabels": { }} test_input_pdb_0_max_unavailable { - input := {"review": input_pdb_max_unavailable(0)} - results := violation with input as input + inp := {"review": input_pdb_max_unavailable(0)} + results := violation with input as inp count(results) == 1 } test_input_pdb_1_max_unavailable { - input := {"review": input_pdb_max_unavailable(1)} - results := violation with input as input + inp := {"review": input_pdb_max_unavailable(1)} + results := violation with input as inp count(results) == 0 } test_input_deployment_1_replica_pdb_1_min_available { - input := {"review": input_deployment(1)} + inp := {"review": input_deployment(1)} inv := inv_pdb_min_available(1) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_deployment_2_replicas_pdb_1_min_available { - input := {"review": input_deployment(2)} + inp := {"review": input_deployment(2)} inv := inv_pdb_min_available(1) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_deployment_pdb_0_max_unavailable { - input := {"review": input_deployment(2)} + inp := {"review": input_deployment(2)} inv := inv_pdb_max_unavailable(0) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_deployment_pdb_1_max_unavailable { - input := {"review": input_deployment(2)} + inp := {"review": input_deployment(2)} inv := inv_pdb_max_unavailable(1) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } diff --git a/src/general/replicalimits/constraint.tmpl b/src/general/replicalimits/constraint.tmpl index 2b4dc9183..55a380360 100644 --- a/src/general/replicalimits/constraint.tmpl +++ b/src/general/replicalimits/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8sreplicalimits annotations: metadata.gatekeeper.sh/title: "Replica Limits" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires that objects with the field `spec.replicas` (Deployments, ReplicaSets, etc.) specify a number of replicas within defined ranges. diff --git a/src/general/replicalimits/src.rego b/src/general/replicalimits/src.rego index 796000da2..066fe924b 100644 --- a/src/general/replicalimits/src.rego +++ b/src/general/replicalimits/src.rego @@ -10,7 +10,7 @@ violation[{"msg": msg}] { } input_replica_limit(spec) { - provided := input.review.object.spec.replicas + provided := spec.replicas count(input.parameters.ranges) > 0 range := input.parameters.ranges[_] value_within_range(range, provided) diff --git a/src/general/replicalimits/src_test.rego b/src/general/replicalimits/src_test.rego index 26a9a201b..5cb1f8a97 100644 --- a/src/general/replicalimits/src_test.rego +++ b/src/general/replicalimits/src_test.rego @@ -1,44 +1,44 @@ package k8sreplicalimits test_input_empty { - input := { "review": empty, "parameters": {}} - results := violation with input as input + inp := { "review": empty, "parameters": {}} + results := violation with input as inp count(results) == 0 } test_input_within_required_replicas { - input := { "review": review(6), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := { "review": review(6), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 0 } test_input_exact_required_replicas_min { - input := { "review": review(5), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := { "review": review(5), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 0 } test_input_exact_required_replicas_max { - input := { "review": review(35), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := { "review": review(35), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 0 } test_input_not_enough_required_replicas { - input := { "review": review(1), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := { "review": review(1), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 1 } test_input_too_many_replicas { - input := { "review": review(100), "parameters": input_parameters_valid_range} - results := violation with input as input + inp := { "review": review(100), "parameters": input_parameters_valid_range} + results := violation with input as inp count(results) == 1 } test_input_zero_replicas { - input := { "review": review(0), "parameters": input_parameters_zero_range} - results := violation with input as input + inp := { "review": review(0), "parameters": input_parameters_zero_range} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/requiredannotations/constraint.tmpl b/src/general/requiredannotations/constraint.tmpl index 0f3a7d2bf..869ab9994 100644 --- a/src/general/requiredannotations/constraint.tmpl +++ b/src/general/requiredannotations/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8srequiredannotations annotations: metadata.gatekeeper.sh/title: "Required Annotations" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified annotations, with values matching provided regular expressions. diff --git a/src/general/requiredannotations/src.rego b/src/general/requiredannotations/src.rego index 248c6cbbe..f9f624a80 100644 --- a/src/general/requiredannotations/src.rego +++ b/src/general/requiredannotations/src.rego @@ -13,6 +13,6 @@ violation[{"msg": msg}] { expected := input.parameters.annotations[_] expected.key == key expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) msg := sprintf("Annotation <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) } diff --git a/src/general/requiredannotations/src_test.rego b/src/general/requiredannotations/src_test.rego index de7de5e85..a9ab36b0b 100644 --- a/src/general/requiredannotations/src_test.rego +++ b/src/general/requiredannotations/src_test.rego @@ -1,63 +1,63 @@ package k8srequiredannotations test_input_no_required_annotations { - input := { "review": review({"some": "annotation"}), "parameters": {}} - results := violation with input as input + inp := { "review": review({"some": "annotation"}), "parameters": {}} + results := violation with input as inp count(results) == 0 } test_input_no_required_annotations { - input := { "review": empty, "parameters": {}} - results := violation with input as input + inp := { "review": empty, "parameters": {}} + results := violation with input as inp count(results) == 0 } test_input_has_annotation { - input := { "review": review({"some": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation")]}} - results := violation with input as input + inp := { "review": review({"some": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation")]}} + results := violation with input as inp count(results) == 0 } test_input_has_extra_annotation { - input := { "review": review({"some": "annotation", "new": "thing"}), "parameters": {"annotations": [lbl("some", "annotation")]}} - results := violation with input as input + inp := { "review": review({"some": "annotation", "new": "thing"}), "parameters": {"annotations": [lbl("some", "annotation")]}} + results := violation with input as inp count(results) == 0 } test_input_has_extra_annotation_req2 { - input := { "review": review({"some": "annotation", "new": "thing"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("new", "thing")]}} - results := violation with input as input + inp := { "review": review({"some": "annotation", "new": "thing"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("new", "thing")]}} + results := violation with input as inp count(results) == 0 } test_input_missing_annotation { - input := { "review": review({"some_other": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation")]}} - results := violation with input as input + inp := { "review": review({"some_other": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation")]}} + results := violation with input as inp count(results) == 1 } test_input_wrong_value { - input := { "review": review({"some": "annotation2"}), "parameters": {"annotations": [lbl("some", "annotation$")]}} - results := violation with input as input + inp := { "review": review({"some": "annotation2"}), "parameters": {"annotations": [lbl("some", "annotation$")]}} + results := violation with input as inp count(results) == 1 } test_input_one_missing { - input := { "review": review({"some": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} - results := violation with input as input + inp := { "review": review({"some": "annotation"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} + results := violation with input as inp count(results) == 1 } test_input_wrong_empty { - input := { "review": empty, "parameters": {"annotations": [lbl("some", "label$")]}} - results := violation with input as input + inp := { "review": empty, "parameters": {"annotations": [lbl("some", "label$")]}} + results := violation with input as inp count(results) == 1 } test_input_two_missing { - input := { "review": empty, "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} - results := violation with input as input + inp := { "review": empty, "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} + results := violation with input as inp count(results) == 1 } test_input_two_wrong { - input := { "review": review({"some": "lbe", "other": "lbe"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} - results := violation with input as input + inp := { "review": review({"some": "lbe", "other": "lbe"}), "parameters": {"annotations": [lbl("some", "annotation"), lbl("other", "annotation")]}} + results := violation with input as inp count(results) == 2 } test_input_two_allowed { - input := { "review": review({"some": "gray", "other": "grey"}), "parameters": {"annotations": [lbl("some", "gr[ae]y"), lbl("other", "gr[ae]y")]}} - results := violation with input as input + inp := { "review": review({"some": "gray", "other": "grey"}), "parameters": {"annotations": [lbl("some", "gr[ae]y"), lbl("other", "gr[ae]y")]}} + results := violation with input as inp count(results) == 0 } diff --git a/src/general/requiredlabels/constraint.tmpl b/src/general/requiredlabels/constraint.tmpl index a667ac30a..0e368a4be 100644 --- a/src/general/requiredlabels/constraint.tmpl +++ b/src/general/requiredlabels/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8srequiredlabels annotations: metadata.gatekeeper.sh/title: "Required Labels" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified labels, with values matching provided regular expressions. diff --git a/src/general/requiredlabels/src.rego b/src/general/requiredlabels/src.rego index 606cda94b..df365ea88 100644 --- a/src/general/requiredlabels/src.rego +++ b/src/general/requiredlabels/src.rego @@ -1,13 +1,10 @@ package k8srequiredlabels -get_message(parameters, _default) = msg { +get_message(parameters, _default) := _default { not parameters.message - msg := _default } -get_message(parameters, _default) = msg { - msg := parameters.message -} +get_message(parameters, _) := parameters.message violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} @@ -24,7 +21,7 @@ violation[{"msg": msg}] { expected.key == key # do not match if allowedRegex is not defined, or is an empty string expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) def_msg := sprintf("Label <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) msg := get_message(input.parameters, def_msg) } diff --git a/src/general/requiredlabels/src_test.rego b/src/general/requiredlabels/src_test.rego index ce0199075..41b67a4a7 100644 --- a/src/general/requiredlabels/src_test.rego +++ b/src/general/requiredlabels/src_test.rego @@ -1,68 +1,68 @@ package k8srequiredlabels test_input_no_required_labels { - input := { "review": review({"some": "label"}), "parameters": {}} - results := violation with input as input + inp := { "review": review({"some": "label"}), "parameters": {}} + results := violation with input as inp count(results) == 0 } test_input_no_required_labels { - input := { "review": empty, "parameters": {}} - results := violation with input as input + inp := { "review": empty, "parameters": {}} + results := violation with input as inp count(results) == 0 } test_input_has_label { - input := { "review": review({"some": "label"}), "parameters": {"labels": [lbl("some", "label")]}} - results := violation with input as input + inp := { "review": review({"some": "label"}), "parameters": {"labels": [lbl("some", "label")]}} + results := violation with input as inp count(results) == 0 } test_input_has_extra_label { - input := { "review": review({"some": "label", "new": "thing"}), "parameters": {"labels": [lbl("some", "label")]}} - results := violation with input as input + inp := { "review": review({"some": "label", "new": "thing"}), "parameters": {"labels": [lbl("some", "label")]}} + results := violation with input as inp count(results) == 0 } test_input_has_extra_label_req2 { - input := { "review": review({"some": "label", "new": "thing"}), "parameters": {"labels": [lbl("some", "label"), lbl("new", "thing")]}} - results := violation with input as input + inp := { "review": review({"some": "label", "new": "thing"}), "parameters": {"labels": [lbl("some", "label"), lbl("new", "thing")]}} + results := violation with input as inp count(results) == 0 } test_input_missing_label { - input := { "review": review({"some_other": "label"}), "parameters": {"labels": [lbl("some", "label")]}} - results := violation with input as input + inp := { "review": review({"some_other": "label"}), "parameters": {"labels": [lbl("some", "label")]}} + results := violation with input as inp count(results) == 1 } test_input_wrong_value { - input := { "review": review({"some": "label2"}), "parameters": {"labels": [lbl("some", "label$")]}} - results := violation with input as input + inp := { "review": review({"some": "label2"}), "parameters": {"labels": [lbl("some", "label$")]}} + results := violation with input as inp count(results) == 1 } test_input_one_missing { - input := { "review": review({"some": "label"}), "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} - results := violation with input as input + inp := { "review": review({"some": "label"}), "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} + results := violation with input as inp count(results) == 1 } test_input_wrong_empty { - input := { "review": empty, "parameters": {"labels": [lbl("some", "label$")]}} - results := violation with input as input + inp := { "review": empty, "parameters": {"labels": [lbl("some", "label$")]}} + results := violation with input as inp count(results) == 1 } test_input_two_missing { - input := { "review": empty, "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} - results := violation with input as input + inp := { "review": empty, "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} + results := violation with input as inp count(results) == 1 } test_input_two_wrong { - input := { "review": review({"some": "lbe", "other": "lbe"}), "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} - results := violation with input as input + inp := { "review": review({"some": "lbe", "other": "lbe"}), "parameters": {"labels": [lbl("some", "label"), lbl("other", "label")]}} + results := violation with input as inp count(results) == 2 } test_input_two_allowed { - input := { "review": review({"some": "gray", "other": "grey"}), "parameters": {"labels": [lbl("some", "gr[ae]y"), lbl("other", "gr[ae]y")]}} - results := violation with input as input + inp := { "review": review({"some": "gray", "other": "grey"}), "parameters": {"labels": [lbl("some", "gr[ae]y"), lbl("other", "gr[ae]y")]}} + results := violation with input as inp count(results) == 0 } test_input_message { - input := { "review": review({"some": "label2"}), "parameters": {"message": "WRONG_VALUE", "labels": [lbl("some", "label$")]}} - results := violation with input as input + inp := { "review": review({"some": "label2"}), "parameters": {"message": "WRONG_VALUE", "labels": [lbl("some", "label$")]}} + results := violation with input as inp results[_].msg == "WRONG_VALUE" } diff --git a/src/general/requiredprobes/src_test.rego b/src/general/requiredprobes/src_test.rego index 0ad2676e2..e888e3500 100644 --- a/src/general/requiredprobes/src_test.rego +++ b/src/general/requiredprobes/src_test.rego @@ -1,362 +1,321 @@ package k8srequiredprobes test_one_ctr_no_violations { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_one_ctr_readiness_violation { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_one_ctr_liveness_violation { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_one_ctr_all_violations { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest"}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest"}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_no_violations { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_two_ctrs_all_violations_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest"}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest"}, {"name": "my-container2","image": "my-image:latest"}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 4 } test_two_ctrs_all_violations_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest"}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest"}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_all_violations_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest"}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_readiness_violation_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_readiness_violation_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, {"name": "my-container2","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_readiness_violation_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_liveness_violation_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_liveness_violation_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_liveness_violation_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_readiness_in_one_liveness_in_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_liveness_in_one_readiness_in_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_readiness_violation_in_ctr_one_all_violations_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest"}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_liveness_violation_in_ctr_one_all_violations_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest"}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_readiness_violation_in_ctr_two_all_violations_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest"}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest"}, {"name": "my-container2","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_liveness_violation_in_ctr_two_all_violations_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest"}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest"}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_one_ctr_empty_readiness_violation { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_one_ctr_empty_liveness_violation { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_one_ctr_empty_probes_violations { - kind := kinds[_] - input := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), + inp := {"review": review([{"name": "my-container","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_probes_violation_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 4 } test_two_ctrs_empty_probes_violation_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_probes_violation_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_readiness_violation_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}, "readinessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}, "readinessProbe": {}}, {"name": "my-container2","image": "my-image:latest","readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_empty_readiness_violation_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_empty_readiness_violation_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_liveness_violation_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_empty_liveness_violation_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {"tcpSocket": {"port":8080}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_two_ctrs_empty_liveness_violation_in_both { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_readiness_in_ctr_one_empty_liveness_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe":{}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe":{}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":8080}}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_liveness_in_one_empty_readiness_in_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":8080}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_two_ctrs_empty_readiness_in_ctr_one_both_empty_probes_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_empty_liveness_in_ctr_one_both_empty_probes_in_ctr_two { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_empty_readiness_in_ctr_two_both_empty_probes_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {"tcpSocket": {"port":80}}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_two_ctrs_empty_liveness_in_ctr_two_both_empty_probes_in_ctr_one { - kind := kinds[_] - input := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, + inp := {"review": review([{"name": "my-container1","image": "my-image:latest", "readinessProbe": {}, "livenessProbe": {}}, {"name": "my-container2","image": "my-image:latest", "readinessProbe": {"tcpSocket": {"port":80}}, "livenessProbe": {}}]), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 3 } test_update { - kind := kinds[_] - input := {"review": object.union(review([{"name": "my-container","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), {"operation": "UPDATE"}), + inp := {"review": object.union(review([{"name": "my-container","image": "my-image:latest", "livenessProbe": {"tcpSocket": {"port":80}}}]), {"operation": "UPDATE"}), "parameters": parameters} - results := violation with input as input + results := violation with input as inp count(results) == 0 } -review(containers) = obj { - obj = { - "kind": { - "kind": "Pod" - }, - "object": { - "metadata": { - "name": "some-name" - }, - "spec": { - "containers":containers - } - } +review(containers) := { + "kind": { + "kind": "Pod" + }, + "object": { + "metadata": { + "name": "some-name" + }, + "spec": { + "containers": containers } + } } parameters = {"probes": ["readinessProbe", "livenessProbe"], "probeTypes": ["tcpSocket", "httpGet", "exec"]} diff --git a/src/general/storageclass/src_test.rego b/src/general/storageclass/src_test.rego index 7a0e55b5c..4064c61d3 100644 --- a/src/general/storageclass/src_test.rego +++ b/src/general/storageclass/src_test.rego @@ -1,94 +1,94 @@ package k8sstorageclass test_input_denied_no_datasync { - input := { "review": input_review_pvc_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv_nosync + inp := { "review": input_review_pvc_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv_nosync results[result] contains(result.msg, "misconfigured") } test_input_allowed_pvc_fast { - input := { "review": input_review_pvc_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_allowed_pvc_slow { - input := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_pvc_bad_storageclassname { - input := { "review": input_review_pvc_name("other"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("other"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_denied_pvc_bad_storageclassname_excludestorageclassesinmessage { - input := { "review": input_review_pvc_name("other"), "parameters": { "includeStorageClassesInMessage": false } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("other"), "parameters": { "includeStorageClassesInMessage": false } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_denied_pvc_storageclassname_missing { - input := { "review": input_review_pvc_storageclassname_missing, "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_storageclassname_missing, "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_allowed_pvc_sc { - input := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["slow"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["slow"] } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_pvc_sc { - input := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast"] } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_allowed_pvc_mixed_sc { - input := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast", "slow"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast", "slow"] } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_pvc_multiple_sc { - input := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["other", "fast"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_pvc_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["other", "fast"] } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_allowed_statefulset_fast { - input := { "review": input_review_statefulset_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("fast"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_allowed_statefulset_slow { - input := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_statefulset_bad_storageclassname { - input := { "review": input_review_statefulset_name("other"), "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("other"), "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_denied_statefulset_storageclassname_missing { - input := { "review": input_review_statefulset_storageclassname_missing, "parameters": { "includeStorageClassesInMessage": true } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_storageclassname_missing, "parameters": { "includeStorageClassesInMessage": true } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_allowed_statefulset_sc { - input := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["slow"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["slow"] } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_statefulset_sc { - input := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast"] } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_input_allowed_statefulset_mixed_sc { - input := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast", "slow"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["fast", "slow"] } } + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_input_denied_statefulset_multiple_sc { - input := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["other","fast"] } } - results := violation with input as input with data.inventory as inv + inp := { "review": input_review_statefulset_name("slow"), "parameters": { "includeStorageClassesInMessage": true, "allowedStorageClasses": ["other","fast"] } } + results := violation with input as inp with data.inventory as inv count(results) == 1 } diff --git a/src/general/uniqueingresshost/constraint.tmpl b/src/general/uniqueingresshost/constraint.tmpl index e546c9098..e8fb572de 100644 --- a/src/general/uniqueingresshost/constraint.tmpl +++ b/src/general/uniqueingresshost/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/version: 1.0.4 metadata.gatekeeper.sh/requires-sync-data: | "[ [ diff --git a/src/general/uniqueingresshost/src.rego b/src/general/uniqueingresshost/src.rego index 899c17c12..24bb68d13 100644 --- a/src/general/uniqueingresshost/src.rego +++ b/src/general/uniqueingresshost/src.rego @@ -7,10 +7,10 @@ identical(obj, review) { violation[{"msg": msg}] { input.review.kind.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)$", input.review.kind.group) + regex.match("^(extensions|networking.k8s.io)$", input.review.kind.group) host := input.review.object.spec.rules[_].host other := data.inventory.namespace[_][otherapiversion]["Ingress"][name] - re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion) + regex.match("^(extensions|networking.k8s.io)/.+$", otherapiversion) other.spec.rules[_].host == host not identical(other, input.review) msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host]) diff --git a/src/general/uniqueingresshost/src_test.rego b/src/general/uniqueingresshost/src_test.rego index b34ca1685..1368c4191 100644 --- a/src/general/uniqueingresshost/src_test.rego +++ b/src/general/uniqueingresshost/src_test.rego @@ -1,78 +1,78 @@ package k8suniqueingresshost test_no_data { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} - results := violation with input as input + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} + results := violation with input as inp count(results) == 0 } test_identical { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} inv := inventory_data([ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1")]) trace(sprintf("%v", [inv])) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv trace(sprintf("%v", [results])) count(results) == 0 } test_collision { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_collision_with_multiple { - input := {"review": review(ingress("my-ingress", "prod", my_rules3, "extensions/v1beta1"), "extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules3, "extensions/v1beta1"), "extensions")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1"), ingress("my-ingress1", "prod2", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 2 } test_no_collision { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "extensions/v1beta1"), "extensions")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_no_collision_with_multiple { - input := {"review": review(ingress("my-ingress", "prod", my_rules4, "extensions/v1beta1"), "extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules4, "extensions/v1beta1"), "extensions")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_no_collision_with_multiple_apis { - input := {"review": review(ingress("my-ingress", "prod", my_rules4, "networking.k8s.io/v1beta1"), "networking.k8s.io")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules4, "networking.k8s.io/v1beta1"), "networking.k8s.io")} inv := inventory_data2([ingress("my-ingress", "prod2", my_rules1, "networking.k8s.io/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "networking.k8s.io/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_collision_with_multiple_apis { - input := {"review": review(ingress("my-ingress", "prod", my_rules3, "networking.k8s.io/v1beta1"), "networking.k8s.io")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules3, "networking.k8s.io/v1beta1"), "networking.k8s.io")} inv := inventory_data2([ingress("my-ingress", "prod2", my_rules1, "networking.k8s.io/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "networking.k8s.io/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 2 } test_no_collision_with_multiple_bad_review_apis { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "app/v1beta1"), "app")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "app/v1beta1"), "app")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_no_collision_with_multiple_bad_review_apis2 { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "test.extensions/v1beta1"), "test.extensions")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "test.extensions/v1beta1"), "test.extensions")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_collision_with_multiple_apis_mixed { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "networking.k8s.io/v1beta1"), "networking.k8s.io")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "networking.k8s.io/v1beta1"), "networking.k8s.io")} inv := inventory_data([ingress("my-ingress", "prod2", my_rules1, "extensions/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "extensions/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_no_collision_with_multiple_apis_slash { - input := {"review": review(ingress("my-ingress", "prod", my_rules1, "networking.k8s.io/v1beta1"), "networking.k8s.io")} + inp := {"review": review(ingress("my-ingress", "prod", my_rules1, "networking.k8s.io/v1beta1"), "networking.k8s.io")} inv := inventory_data1([ingress("my-ingress", "prod2", my_rules1, "extensions.something.io/v1beta1"), ingress("my-ingress", "prod3", my_rules2, "extensions.something.io/v1beta1")]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } @@ -92,7 +92,7 @@ review(ing, group) = output { } my_rule(host) = { - "host": host, + "host": host, "http": { "paths": [{"backend": {"serviceName": "nginx", "servicePort": 80}}] }, diff --git a/src/general/uniqueserviceselector/src_test.rego b/src/general/uniqueserviceselector/src_test.rego index 316d635a3..84ac349fb 100644 --- a/src/general/uniqueserviceselector/src_test.rego +++ b/src/general/uniqueserviceselector/src_test.rego @@ -1,55 +1,55 @@ package k8suniqueserviceselector test_no_data { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} - results := violation with input as input + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} + results := violation with input as inp count(results) == 0 } test_identical { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} inv := tmp_data([service("my-service", "prod", {"a": "b"})]) trace(sprintf("%v", [inv])) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv trace(sprintf("%v", [results])) count(results) == 0 } test_collision { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} inv := tmp_data([service("my-service", "prod2", {"a": "b"})]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_collision_with_multiple { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} inv := tmp_data([service("my-service", "prod2", {"a": "b"}), service("my-service", "prod3", {"a": "b"})]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 2 } test_no_collision { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} inv := tmp_data([service("my-service", "prod2", {"a": "c"})]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_no_collision_with_multiple { - input := {"review": review(service("my-service", "prod", {"a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"a": "b"}))} inv := tmp_data([service("my-service", "prod2", {"a": "b2"}), service("my-service", "prod3", {"a": "b2"})]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } test_compound_selector_collision { - input := {"review": review(service("my-service", "prod", {"r": "d", "a": "b"}))} + inp := {"review": review(service("my-service", "prod", {"r": "d", "a": "b"}))} inv := tmp_data([service("my-service", "prod2", {"a": "b", "r": "d"})]) - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 1 } test_no_service_selector { - input := {"review": review(service_without_selector("kubernetes", "default"))} + inp := {"review": review(service_without_selector("kubernetes", "default"))} inv := data_networkpolicy("default") - results := violation with input as input with data.inventory as inv + results := violation with input as inp with data.inventory as inv count(results) == 0 } diff --git a/src/general/verifydeprecatedapi/src_test.rego b/src/general/verifydeprecatedapi/src_test.rego index 37155123d..a8f6a27a5 100644 --- a/src/general/verifydeprecatedapi/src_test.rego +++ b/src/general/verifydeprecatedapi/src_test.rego @@ -1,14 +1,14 @@ package verifydeprecatedapi test_hpa_with_deprecated_api { - input := {"review": hpa("autoscaling/v2beta2"), "parameters": {"kvs": [{"deprecatedAPI": "autoscaling/v2beta2", "kinds": ["HorizontalPodAutoscaler"], "targetAPI": "autoscaling/v2"}], "k8sVersion": 1.26}} - results := violation with input as input + inp := {"review": hpa("autoscaling/v2beta2"), "parameters": {"kvs": [{"deprecatedAPI": "autoscaling/v2beta2", "kinds": ["HorizontalPodAutoscaler"], "targetAPI": "autoscaling/v2"}], "k8sVersion": 1.26}} + results := violation with input as inp count(results) == 0 } test_hpa_without_deprecated_api { - input := {"review": hpa("autoscaling/v2"), "parameters": {"kvs": [{"deprecatedAPI": "autoscaling/v2beta2", "kinds": ["HorizontalPodAutoscaler"], "targetAPI": "autoscaling/v2"}], "k8sVersion": 1.26}} - results := violation with input as input + inp := {"review": hpa("autoscaling/v2"), "parameters": {"kvs": [{"deprecatedAPI": "autoscaling/v2beta2", "kinds": ["HorizontalPodAutoscaler"], "targetAPI": "autoscaling/v2"}], "k8sVersion": 1.26}} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/allow-privilege-escalation/src_test.rego b/src/pod-security-policy/allow-privilege-escalation/src_test.rego index a8e380d1f..8c1645675 100644 --- a/src/pod-security-policy/allow-privilege-escalation/src_test.rego +++ b/src/pod-security-policy/allow-privilege-escalation/src_test.rego @@ -1,48 +1,48 @@ package k8spspallowprivilegeescalationcontainer test_input_container_not_privilege_escalation_allowed { - input := { "review": input_review} - results := violation with input as input + inp := { "review": input_review} + results := violation with input as inp count(results) == 0 } test_input_container_privilege_escalation_not_allowed { - input := { "review": input_review_priv} - results := violation with input as input + inp := { "review": input_review_priv} + results := violation with input as inp count(results) == 1 } test_input_one_container_with_exemption { - input := { "review": input_review_priv, "parameters": {"exemptImages": ["one/*"]}} - results := violation with input as input + inp := { "review": input_review_priv, "parameters": {"exemptImages": ["one/*"]}} + results := violation with input as inp count(results) == 0 } test_input_container_many_not_privilege_escalation_allowed { - input := { "review": input_review_many} - results := violation with input as input + inp := { "review": input_review_many} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_privilege_escalation_not_allowed { - input := { "review": input_review_many_mixed} - results := violation with input as input + inp := { "review": input_review_many_mixed} + results := violation with input as inp count(results) == 3 } test_input_container_many_mixed_privilege_escalation_not_allowed_one_exempted { - input := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*"]}} - results := violation with input as input + inp := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*"]}} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_privilege_escalation_not_allowed_all_exempted { - input := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*", "two/*", "three/*"]}} - results := violation with input as input + inp := { "review": input_review_many_mixed, "parameters": {"exemptImages": ["one/*", "two/*", "three/*"]}} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_privilege_escalation_not_allowed_two { - input := { "review": input_review_many_mixed_two} - results := violation with input as input + inp := { "review": input_review_many_mixed_two} + results := violation with input as inp count(results) == 2 } test_update { - input := { "review": object.union(input_review_priv, {"operation": "UPDATE"})} - results := violation with input as input + inp := { "review": object.union(input_review_priv, {"operation": "UPDATE"})} + results := violation with input as inp count(results) == 0 } @@ -140,7 +140,7 @@ input_containers_many = [ "securityContext": { "runAsUser": "1000" } - + }] input_containers_many_mixed = [ diff --git a/src/pod-security-policy/apparmor/src_test.rego b/src/pod-security-policy/apparmor/src_test.rego index dbed04d28..70c18fad1 100644 --- a/src/pod-security-policy/apparmor/src_test.rego +++ b/src/pod-security-policy/apparmor/src_test.rego @@ -1,68 +1,68 @@ package k8spspapparmor test_input_apparmor_allowed_empty { - input := { "review": input_review_container, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_container, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_apparmor_allowed_empty_but_exempted { - input := { "review": input_review_container, "parameters": input_parameters_exempt_container} - results := violation with input as input + inp := { "review": input_review_container, "parameters": input_parameters_exempt_container} + results := violation with input as inp count(results) == 1 } test_input_apparmor_not_allowed_no_annotation_empty { - input := { "review": input_review_no_annotation, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_no_annotation, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_apparmor_not_allowed_no_annotation { - input := { "review": input_review_no_annotation, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_no_annotation, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_apparmor_container_allowed_in_list { - input := { "review": input_review_container, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_container, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_apparmor_container_not_allowed_not_in_list { - input := { "review": input_review_container, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_container, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_apparmor_containers_allowed_in_list { - input := { "review": input_review_containers, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_containers, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_apparmor_containers_not_allowed_not_in_list { - input := { "review": input_review_containers, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_containers, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_apparmor_containers_allowed_in_list_mixed_no_annotation { - input := { "review": input_review_containers_missing_annotation, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_containers_missing_annotation, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_apparmor_containers_not_allowed_not_in_list_mixed_no_annotation { - input := { "review": input_review_containers_missing_annotation, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_containers_missing_annotation, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_apparmor_containers_not_allowed_not_in_list_mixed { - input := { "review": input_review_containers_mixed, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_containers_mixed, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 1 } diff --git a/src/pod-security-policy/capabilities/constraint.tmpl b/src/pod-security-policy/capabilities/constraint.tmpl index 88bd9e262..9ca6bed26 100644 --- a/src/pod-security-policy/capabilities/constraint.tmpl +++ b/src/pod-security-policy/capabilities/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspcapabilities annotations: metadata.gatekeeper.sh/title: "Capabilities" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a diff --git a/src/pod-security-policy/capabilities/src.rego b/src/pod-security-policy/capabilities/src.rego index b60b26a3f..35038a95c 100644 --- a/src/pod-security-policy/capabilities/src.rego +++ b/src/pod-security-policy/capabilities/src.rego @@ -75,12 +75,9 @@ missing_drop_capabilities(container) { count(all - dropped) > 0 } -get_default(obj, param, _default) = out { - out = obj[param] -} +get_default(obj, param, _) := obj[param] -get_default(obj, param, _default) = out { +get_default(obj, param, _default) := _default { not obj[param] not obj[param] == false - out = _default } diff --git a/src/pod-security-policy/capabilities/src_test.rego b/src/pod-security-policy/capabilities/src_test.rego index 6158a3eea..4ab7bd0cc 100644 --- a/src/pod-security-policy/capabilities/src_test.rego +++ b/src/pod-security-policy/capabilities/src_test.rego @@ -1,281 +1,281 @@ package capabilities test_input_all_allowed { - input := { "review": input_review([cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["*"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["*"]}} + results := violation with input as inp count(results) == 0 } test_input_all_allowed_container_x2 { - input := { "review": input_review([cadd(["one", "two"]), cadd(["three"])]), "parameters": {"allowedCapabilities": ["*"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one", "two"]), cadd(["three"])]), "parameters": {"allowedCapabilities": ["*"]}} + results := violation with input as inp count(results) == 0 } test_input_one_allowed { - input := { "review": input_review([cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} + results := violation with input as inp count(results) == 0 } test_input_one_allowed_container_x2 { - input := { "review": input_review([cadd(["one"]), cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"]), cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} + results := violation with input as inp count(results) == 0 } test_input_two_allowed_container_x2 { - input := { "review": input_review([cadd(["one"]), cadd(["two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"]), cadd(["two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_two_allowed_two_used_container_x2 { - input := { "review": input_review([cadd(["one", "two"]), cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one", "two"]), cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_none_allowed { - input := { "review": input_review([cadd(["one"])]), "parameters": {"allowedCapabilities": []}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"])]), "parameters": {"allowedCapabilities": []}} + results := violation with input as inp count(results) == 1 } test_input_none_allowed_undefined { - input := { "review": input_review([cadd(["one"])]), "parameters": {}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"])]), "parameters": {}} + results := violation with input as inp count(results) == 1 } test_input_none_allowed_undefined_x2_x2 { - input := { "review": input_review([cadd(["one", "two"]), cadd(["three", "two"])]), "parameters": {}} - results := violation with input as input + inp := { "review": input_review([cadd(["one", "two"]), cadd(["three", "two"])]), "parameters": {}} + results := violation with input as inp trace(sprintf("results are: %v", [results])) count(results) == 2 } test_input_disallowed_x1 { - input := { "review": input_review([cadd(["three"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["three"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_disallowed_x2_just_one { - input := { "review": input_review([cadd(["one"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["one"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_disallowed_x2 { - input := { "review": input_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_disallowed_x2_but_exempt { - input := { "review": input_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} - results := violation with input as input + inp := { "review": input_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} + results := violation with input as inp count(results) == 0 } test_input_empty_drop { - input := { "review": input_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": []}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": []}} + results := violation with input as inp count(results) == 0 } test_input_all_dropped { - input := { "review": input_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_extra_dropped { - input := { "review": input_review([cdrop(["one", "two", "three"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one", "two", "three"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_all_dropped_x2 { - input := { "review": input_review([cdrop(["one", "two"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one", "two"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_missing_drop { - input := { "review": input_review([cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_one_missing_drop_x2 { - input := { "review": input_review([cdrop(["one"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_missing_drop_x2 { - input := { "review": input_review([cdrop(["one"]), cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["one"]), cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_drop_undefined_x2 { - input := { "review": input_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_drop_undefined_x2_but_exempt { - input := { "review": input_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} - results := violation with input as input + inp := { "review": input_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all { - input := { "review": input_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all_lower { - input := { "review": input_review([cdrop(["all"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["all"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all_with_all_param { - input := { "review": input_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all_x2 { - input := { "review": input_review([cdrop(["ALL", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_review([cdrop(["ALL", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review([cadd(["one"])]), {"operation": "UPDATE"}), "parameters": {"allowedCapabilities": []}} - results := violation with input as input + inp := { "review": object.union(input_review([cadd(["one"])]), {"operation": "UPDATE"}), "parameters": {"allowedCapabilities": []}} + results := violation with input as inp count(results) == 0 } # init containers test_input_all_allowed { - input := { "review": input_init_review([cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["*"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["*"]}} + results := violation with input as inp count(results) == 0 } test_input_all_allowed_container_x2 { - input := { "review": input_init_review([cadd(["one", "two"]), cadd(["three"])]), "parameters": {"allowedCapabilities": ["*"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one", "two"]), cadd(["three"])]), "parameters": {"allowedCapabilities": ["*"]}} + results := violation with input as inp count(results) == 0 } test_input_one_allowed { - input := { "review": input_init_review([cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} + results := violation with input as inp count(results) == 0 } test_input_one_allowed_container_x2 { - input := { "review": input_init_review([cadd(["one"]), cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"]), cadd(["one"])]), "parameters": {"allowedCapabilities": ["one"]}} + results := violation with input as inp count(results) == 0 } test_input_two_allowed_container_x2 { - input := { "review": input_init_review([cadd(["one"]), cadd(["two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"]), cadd(["two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_two_allowed_two_used_container_x2 { - input := { "review": input_init_review([cadd(["one", "two"]), cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one", "two"]), cadd(["one", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_none_allowed { - input := { "review": input_init_review([cadd(["one"])]), "parameters": {"allowedCapabilities": []}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"])]), "parameters": {"allowedCapabilities": []}} + results := violation with input as inp count(results) == 1 } test_input_none_allowed_undefined { - input := { "review": input_init_review([cadd(["one"])]), "parameters": {}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"])]), "parameters": {}} + results := violation with input as inp count(results) == 1 } test_input_none_allowed_undefined_x2_x2 { - input := { "review": input_init_review([cadd(["one", "two"]), cadd(["three", "two"])]), "parameters": {}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one", "two"]), cadd(["three", "two"])]), "parameters": {}} + results := violation with input as inp count(results) == 2 } test_input_disallowed_x1 { - input := { "review": input_init_review([cadd(["three"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["three"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_disallowed_x2_just_one { - input := { "review": input_init_review([cadd(["one"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["one"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_disallowed_x2 { - input := { "review": input_init_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_disallowed_x2_but_exempt { - input := { "review": input_init_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd(["three"]), cadd(["three", "two"])]), "parameters": {"allowedCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} + results := violation with input as inp count(results) == 0 } test_input_empty_drop { - input := { "review": input_init_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": []}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": []}} + results := violation with input as inp count(results) == 0 } test_input_all_dropped { - input := { "review": input_init_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_extra_dropped { - input := { "review": input_init_review([cdrop(["one", "two", "three"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one", "two", "three"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_all_dropped_x2 { - input := { "review": input_init_review([cdrop(["one", "two"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one", "two"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_missing_drop { - input := { "review": input_init_review([cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_one_missing_drop_x2 { - input := { "review": input_init_review([cdrop(["one"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one"]), cdrop(["one", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 1 } test_input_missing_drop_x2 { - input := { "review": input_init_review([cdrop(["one"]), cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one"]), cdrop(["two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_drop_undefined_x2 { - input := { "review": input_init_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 2 } test_input_drop_undefined_x2_but_exempt { - input := { "review": input_init_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} - results := violation with input as input + inp := { "review": input_init_review([cadd([]), cadd([])]), "parameters": {"requiredDropCapabilities": ["one", "two"], "exemptImages": ["nginx"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all { - input := { "review": input_init_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all_lower { - input := { "review": input_init_review([cdrop(["all"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["all"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_all_with_all_param { - input := { "review": input_init_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["ALL"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} + results := violation with input as inp count(results) == 0 } test_input_drop_literal_with_all_param { - input := { "review": input_init_review([cdrop(["one"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["one"])]), "parameters": {"requiredDropCapabilities": ["one", "ALL"]}} + results := violation with input as inp count(results) == 1 } test_input_drop_literal_all_x2 { - input := { "review": input_init_review([cdrop(["ALL", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} - results := violation with input as input + inp := { "review": input_init_review([cdrop(["ALL", "two"])]), "parameters": {"requiredDropCapabilities": ["one", "two"]}} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/flexvolume-drivers/src_test.rego b/src/pod-security-policy/flexvolume-drivers/src_test.rego index 3b8eb69be..aa7d310b4 100644 --- a/src/pod-security-policy/flexvolume-drivers/src_test.rego +++ b/src/pod-security-policy/flexvolume-drivers/src_test.rego @@ -1,62 +1,62 @@ package k8spspflexvolumes test_input_flexvolume_empty_params { - input := { "review": input_review, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_flexvolume_many_empty_params{ - input := { "review": input_review_many, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 2 } test_input_no_flexvolume_is_allowed { - input := { "review": input_review_no_flexvolume, "parameters": input_parameter_in_list} - results := violation with input as input + inp := { "review": input_review_no_flexvolume, "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_flexvolume_allowed { - input := { "review": input_review, "parameters": input_parameter_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_flexvolume_many_is_allowed { - input := { "review": input_review_many, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_flexvolume_many_is_allowed_no_flexvolume { - input := { "review": input_review_many_no_flexvolume, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many_no_flexvolume, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_flexvolume_not_allowed { - input := { "review": input_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_flexvolume_many_not_allowed { - input := { "review": input_review_many_not_allowed, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many_not_allowed, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_flexvolume_many_one_allowed { - input := { "review": input_review_many, "parameters": input_parameter_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_flexvolume_many_mixed_allowed { - input := { "review": input_review_many, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/forbidden-sysctls/constraint.tmpl b/src/pod-security-policy/forbidden-sysctls/constraint.tmpl index 91cecf030..87e4d23a9 100644 --- a/src/pod-security-policy/forbidden-sysctls/constraint.tmpl +++ b/src/pod-security-policy/forbidden-sysctls/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspforbiddensysctls annotations: metadata.gatekeeper.sh/title: "Forbidden Sysctls" - metadata.gatekeeper.sh/version: 1.1.2 + metadata.gatekeeper.sh/version: 1.1.3 description: >- Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. diff --git a/src/pod-security-policy/forbidden-sysctls/src.rego b/src/pod-security-policy/forbidden-sysctls/src.rego index 359dd44c7..135603aa1 100644 --- a/src/pod-security-policy/forbidden-sysctls/src.rego +++ b/src/pod-security-policy/forbidden-sysctls/src.rego @@ -21,7 +21,7 @@ violation[{"msg": msg, "details": {}}] { } # * may be used to forbid all sysctls -forbidden_sysctl(sysctl) { +forbidden_sysctl(_) { input.parameters.forbiddenSysctls[_] == "*" } @@ -36,7 +36,7 @@ forbidden_sysctl(sysctl) { } # * may be used to allow all sysctls -allowed_sysctl(sysctl) { +allowed_sysctl(_) { input.parameters.allowedSysctls[_] == "*" } diff --git a/src/pod-security-policy/forbidden-sysctls/src_test.rego b/src/pod-security-policy/forbidden-sysctls/src_test.rego index d2bd78027..07189ea47 100644 --- a/src/pod-security-policy/forbidden-sysctls/src_test.rego +++ b/src/pod-security-policy/forbidden-sysctls/src_test.rego @@ -1,116 +1,116 @@ package k8spspforbiddensysctls test_input_sysctls_forbidden_all { - input := { "review": input_review, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 2 } test_input_sysctls_forbidden_in_list { - input := { "review": input_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 2 } test_input_sysctls_forbidden_in_list_mixed { - input := { "review": input_review, "parameters": input_parameters_one_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_one_in_list} + results := violation with input as inp count(results) == 1 } test_input_sysctls_forbidden_not_in_list { - input := { "review": input_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 0 } test_input_sysctls_forbidden_in_list_wildcard { - input := { "review": input_review, "parameters": input_parameters_in_list_wildcard} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_wildcard} + results := violation with input as inp count(results) == 2 } test_input_sysctls_forbidden_in_list_wildcard_mixed { - input := { "review": input_review, "parameters": input_parameters_one_in_list_wildcard} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_one_in_list_wildcard} + results := violation with input as inp count(results) == 1 } test_input_sysctls_forbidden_not_in_list_wildcard { - input := { "review": input_review, "parameters": input_parameters_not_in_list_wildcard} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list_wildcard} + results := violation with input as inp count(results) == 0 } test_input_sysctls_empty_forbidden { - input := { "review": input_review, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } test_input_seccontext_empty_wildcard { - input := { "review": input_review_seccontext_empty, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review_seccontext_empty, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_sysctls_empty_wildcard { - input := { "review": input_review_sysctls_empty, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review_sysctls_empty, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccontext_null_wildcard { - input := { "review": input_review_seccontext_null, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review_seccontext_null, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccontext_empty_empty_forbidden { - input := { "review": input_review_seccontext_empty, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_seccontext_empty, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } test_input_sysctls_empty_empty_forbidden { - input := { "review": input_review_sysctls_empty, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_sysctls_empty, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } test_input_seccontext_null_empty_forbidden { - input := { "review": input_review_seccontext_null, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_seccontext_null, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } test_input_init_sysctls_forbidden_all { - input := { "review": input_init_review, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 2 } test_input_init_sysctls_forbidden_in_list { - input := { "review": input_init_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 2 } test_input_init_sysctls_forbidden_in_list_mixed { - input := { "review": input_init_review, "parameters": input_parameters_one_in_list} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_one_in_list} + results := violation with input as inp count(results) == 1 } test_input_init_sysctls_forbidden_not_in_list { - input := { "review": input_init_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 0 } test_input_sysctls_allowed_all { - input := { "review": input_review, "parameters": input_parameters_sysctls_allowed_all} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_allowed_all} + results := violation with input as inp count(results) == 0 } @@ -118,44 +118,44 @@ test_input_sysctls_allowed_all { # This is in contrast to unspecified allowedSysctls which does not # place any restrictions by itself. test_input_sysctls_allowed_empty { - input := { "review": input_review, "parameters": input_parameters_sysctls_allowed_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_allowed_empty} + results := violation with input as inp count(results) == 2 } test_input_sysctls_allowed_exact { - input := { "review": input_review, "parameters": input_parameters_sysctls_allowed_exact} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_allowed_exact} + results := violation with input as inp count(results) == 0 } test_input_sysctls_allowed_wildcards { - input := { "review": input_review, "parameters": input_parameters_sysctls_allowed_wildcards} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_allowed_wildcards} + results := violation with input as inp count(results) == 0 } test_input_sysctls_some_allowed_exact { - input := { "review": input_review, "parameters": input_parameters_sysctls_some_allowed_exact} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_some_allowed_exact} + results := violation with input as inp count(results) == 1 } test_input_sysctls_some_allowed_wildcards { - input := { "review": input_review, "parameters": input_parameters_sysctls_some_allowed_wildcards} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_some_allowed_wildcards} + results := violation with input as inp count(results) == 1 } test_input_sysctls_allowed_and_forbidden { - input := { "review": input_review, "parameters": input_parameters_sysctls_allowed_and_forbidden} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_sysctls_allowed_and_forbidden} + results := violation with input as inp count(results) == 2 } test_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/fsgroup/constraint.tmpl b/src/pod-security-policy/fsgroup/constraint.tmpl index 34a8b2a99..01e9f415d 100644 --- a/src/pod-security-policy/fsgroup/constraint.tmpl +++ b/src/pod-security-policy/fsgroup/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspfsgroup annotations: metadata.gatekeeper.sh/title: "FS Group" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls allocating an FSGroup that owns the Pod's volumes. Corresponds to the `fsGroup` field in a PodSecurityPolicy. For more information, see diff --git a/src/pod-security-policy/fsgroup/src.rego b/src/pod-security-policy/fsgroup/src.rego index 23690a0de..2eb95cab7 100644 --- a/src/pod-security-policy/fsgroup/src.rego +++ b/src/pod-security-policy/fsgroup/src.rego @@ -11,7 +11,7 @@ violation[{"msg": msg, "details": {}}] { msg := sprintf("The provided pod spec fsGroup is not allowed, pod: %v. Allowed fsGroup: %v", [input.review.object.metadata.name, input.parameters]) } -input_fsGroup_allowed(spec) { +input_fsGroup_allowed(_) { # RunAsAny - No range is required. Allows any fsGroup ID to be specified. input.parameters.rule == "RunAsAny" } diff --git a/src/pod-security-policy/fsgroup/src_test.rego b/src/pod-security-policy/fsgroup/src_test.rego index 51fcf59f7..ab7be3d58 100644 --- a/src/pod-security-policy/fsgroup/src_test.rego +++ b/src/pod-security-policy/fsgroup/src_test.rego @@ -1,58 +1,58 @@ package k8spspfsgroup test_input_fsgroup_allowed_all { - input := { "review": input_review_with_fsgroup, "parameters": input_parameters_runasany} - results := violation with input as input + inp := { "review": input_review_with_fsgroup, "parameters": input_parameters_runasany} + results := violation with input as inp count(results) == 0 } test_input_no_fsgroup_allowed_all { - input := { "review": input_review, "parameters": input_parameters_runasany} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_runasany} + results := violation with input as inp count(results) == 0 } test_input_fsgroup_MustRunAs_allowed { - input := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mustrunas} - results := violation with input as input + inp := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mustrunas} + results := violation with input as inp count(results) == 0 } test_input_fsgroup_MustRunAs_not_allowed { - input := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mustrunas_outofrange} - results := violation with input as input + inp := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mustrunas_outofrange} + results := violation with input as inp count(results) > 0 } test_input_no_fsgroup_MustRunAs_not_allowed { - input := { "review": input_review, "parameters": input_parameters_in_list_mustrunas} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_mustrunas} + results := violation with input as inp count(results) > 0 } test_input_securitycontext_no_fsgroup_MustRunAs_not_allowed { - input := { "review": input_review_with_securitycontext_no_fsgroup, "parameters": input_parameters_in_list_mustrunas} - results := violation with input as input + inp := { "review": input_review_with_securitycontext_no_fsgroup, "parameters": input_parameters_in_list_mustrunas} + results := violation with input as inp count(results) > 0 } test_input_fsgroup_MayRunAs_allowed { - input := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mayrunas} - results := violation with input as input + inp := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mayrunas} + results := violation with input as inp count(results) == 0 } test_input_fsgroup_MayRunAs_not_allowed { - input := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mayrunas_outofrange} - results := violation with input as input + inp := { "review": input_review_with_fsgroup, "parameters": input_parameters_in_list_mayrunas_outofrange} + results := violation with input as inp count(results) > 0 } test_input_no_fsgroup_MayRunAs_allowed { - input := { "review": input_review, "parameters": input_parameters_in_list_mayrunas} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_mayrunas} + results := violation with input as inp count(results) == 0 } test_input_securitycontext_no_fsgroup_MayRunAs_allowed { - input := { "review": input_review_with_securitycontext_no_fsgroup, "parameters": input_parameters_in_list_mayrunas} - results := violation with input as input + inp := { "review": input_review_with_securitycontext_no_fsgroup, "parameters": input_parameters_in_list_mayrunas} + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review_with_fsgroup, {"operation": "UPDATE"}), "parameters": input_parameters_in_list_mustrunas_outofrange} - results := violation with input as input + inp := { "review": object.union(input_review_with_fsgroup, {"operation": "UPDATE"}), "parameters": input_parameters_in_list_mustrunas_outofrange} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/host-filesystem/constraint.tmpl b/src/pod-security-policy/host-filesystem/constraint.tmpl index 39af451e1..d442ec331 100644 --- a/src/pod-security-policy/host-filesystem/constraint.tmpl +++ b/src/pod-security-policy/host-filesystem/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spsphostfilesystem annotations: metadata.gatekeeper.sh/title: "Host Filesystem" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of the host filesystem. Corresponds to the `allowedHostPaths` field in a PodSecurityPolicy. For more information, diff --git a/src/pod-security-policy/host-filesystem/src.rego b/src/pod-security-policy/host-filesystem/src.rego index 53b140816..991c233f3 100644 --- a/src/pod-security-policy/host-filesystem/src.rego +++ b/src/pod-security-policy/host-filesystem/src.rego @@ -12,7 +12,7 @@ violation[{"msg": msg, "details": {}}] { msg := sprintf("HostPath volume %v is not allowed, pod: %v. Allowed path: %v", [volume, input.review.object.metadata.name, allowedPaths]) } -input_hostpath_violation(allowedPaths, volume) { +input_hostpath_violation(allowedPaths, _) { # An empty list means all host paths are blocked allowedPaths == [] } diff --git a/src/pod-security-policy/host-filesystem/src_test.rego b/src/pod-security-policy/host-filesystem/src_test.rego index 1e85733c3..1c6f632f1 100644 --- a/src/pod-security-policy/host-filesystem/src_test.rego +++ b/src/pod-security-policy/host-filesystem/src_test.rego @@ -1,136 +1,136 @@ package k8spsphostfilesystem test_input_hostpath_block_all { - input := { "review": input_review, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_hostpath_block_all_null_params { - input := { "review": input_review, "parameters": null } - results := violation with input as input + inp := { "review": input_review, "parameters": null } + results := violation with input as inp count(results) == 1 } test_input_hostpath_block_all_no_params { - input := { "review": input_review } - results := violation with input as input + inp := { "review": input_review } + results := violation with input as inp count(results) == 1 } test_input_hostpath_block_all { - input := { "review": input_review_many, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 2 } test_input_hostpath_no_volumes { - input := { "review": input_review_no_volumes, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_no_volumes, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_hostpath_mixed_volumes { - input := { "review": input_review_many_mixed_volumes, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many_mixed_volumes, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_hostpath_mixed_volumes_not_allowed { - input := { "review": input_review_many_mixed_volumes, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many_mixed_volumes, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_no_hostpath { - input := { "review": input_review_many_no_hostpath, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many_no_hostpath, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_hostpath_allowed_readonly { - input := { "review": input_review_many, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_hostpath_not_allowed_readonly { - input := { "review": input_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_many_not_allowed_readonly { - input := { "review": input_review_many, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_hostpath_allowed_writable_allowed { - input := { "review": input_review_writable, "parameters": input_parameters_in_list_writable} - results := violation with input as input + inp := { "review": input_review_writable, "parameters": input_parameters_in_list_writable} + results := violation with input as inp count(results) == 0 } test_input_hostpath_allowed_writable_not_allowed { - input := { "review": input_review_writable, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_writable, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_not_allowed_writable { - input := { "review": input_review_writable, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_writable, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_allowed_not_writable { - input := { "review": input_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_allowed_is_writable { - input := { "review": input_review, "parameters": input_parameters_in_list_writable} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_writable} + results := violation with input as inp count(results) == 0 } test_input_hostpath_not_allowed_is_writable { - input := { "review": input_review, "parameters": input_parameters_not_in_list_writable} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list_writable} + results := violation with input as inp count(results) == 1 } test_input_hostpath_not_allowed { - input := { "review": input_review, "parameters": input_parameters_not_in_list_writable} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list_writable} + results := violation with input as inp count(results) == 1 } test_input_hostpath_allowed_readonly_mixed_parameters { - input := { "review": input_review_many_mixed_writable, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many_mixed_writable, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_allowed_readonly_mixed_parameters { - input := { "review": input_review_many_readonly, "parameters": input_parameters_in_list_mixed_writable} - results := violation with input as input + inp := { "review": input_review_many_readonly, "parameters": input_parameters_in_list_mixed_writable} + results := violation with input as inp count(results) == 0 } test_input_hostpath_allowed_mixed_writable_mixed_parameters { - input := { "review": input_review_many_mixed_writable, "parameters": input_parameters_in_list_mixed_writable} - results := violation with input as input + inp := { "review": input_review_many_mixed_writable, "parameters": input_parameters_in_list_mixed_writable} + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } # Init Containers test_input_hostpath_allowed_readonly_init_containers { - input := { "review": input_init_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_allowed_readonly_many_init_containers { - input := { "review": input_init_review_many, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_init_review_many, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_hostpath_not_allowed_readonly_init_containers { - input := { "review": input_init_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_init_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_hostpath_many_not_allowed_readonly_init_containers { - input := { "review": input_init_review_many, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_init_review_many, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } diff --git a/src/pod-security-policy/host-namespaces/src_test.rego b/src/pod-security-policy/host-namespaces/src_test.rego index f5c13e774..ebea77e21 100644 --- a/src/pod-security-policy/host-namespaces/src_test.rego +++ b/src/pod-security-policy/host-namespaces/src_test.rego @@ -1,28 +1,28 @@ package k8spsphostnamespace test_input_no_hostnamespace_allowed { - input := { "review": input_review} - results := violation with input as input + inp := { "review": input_review} + results := violation with input as inp count(results) == 0 } test_input_hostPID_not_allowed { - input := { "review": input_review_hostPID} - results := violation with input as input + inp := { "review": input_review_hostPID} + results := violation with input as inp count(results) > 0 } test_input_hostIPC_not_allowed { - input := { "review": input_review_hostIPC} - results := violation with input as input + inp := { "review": input_review_hostIPC} + results := violation with input as inp count(results) > 0 } test_input_hostnamespace_both_not_allowed { - input := { "review": input_review_hostnamespace_both} - results := violation with input as input + inp := { "review": input_review_hostnamespace_both} + results := violation with input as inp count(results) > 0 } test_update { - input := { "review": object.union(input_review_hostPID, {"operation": "UPDATE"})} - results := violation with input as input + inp := { "review": object.union(input_review_hostPID, {"operation": "UPDATE"})} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/host-network-ports/constraint.tmpl b/src/pod-security-policy/host-network-ports/constraint.tmpl index abf6653c0..c8fd7a131 100644 --- a/src/pod-security-policy/host-network-ports/constraint.tmpl +++ b/src/pod-security-policy/host-network-ports/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spsphostnetworkingports annotations: metadata.gatekeeper.sh/title: "Host Networking Ports" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and diff --git a/src/pod-security-policy/host-network-ports/src.rego b/src/pod-security-policy/host-network-ports/src.rego index 1038815c8..524f6545c 100644 --- a/src/pod-security-policy/host-network-ports/src.rego +++ b/src/pod-security-policy/host-network-ports/src.rego @@ -16,12 +16,12 @@ input_share_hostnetwork(o) { o.spec.hostNetwork } -input_share_hostnetwork(o) { +input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort < input.parameters.min } -input_share_hostnetwork(o) { +input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort > input.parameters.max } diff --git a/src/pod-security-policy/host-network-ports/src_test.rego b/src/pod-security-policy/host-network-ports/src_test.rego index 0e54e11d4..5e23f6879 100644 --- a/src/pod-security-policy/host-network-ports/src_test.rego +++ b/src/pod-security-policy/host-network-ports/src_test.rego @@ -1,49 +1,49 @@ package k8spsphostnetworkingports test_input_no_hostnetwork_no_port_is_allowed { - input := { "review": input_review, "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_ports} + results := violation with input as inp count(results) == 0 } test_input_no_hostnetwork_allowed_ports_is_allowed { - input := { "review": input_review_no_hostnetwork_allowed_ports, "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": input_review_no_hostnetwork_allowed_ports, "parameters": input_parameters_ports} + results := violation with input as inp count(results) == 0 } test_input_no_hostnetwork_container_ports_not_allowed { - input := { "review": input_review_no_hostnetwork_container_ports_outofrange, "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": input_review_no_hostnetwork_container_ports_outofrange, "parameters": input_parameters_ports} + results := violation with input as inp count(results) > 0 } test_input_with_hostnetwork_is_allowed { - input := { "review": input_review_with_hostnetwork_no_port, "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": input_review_with_hostnetwork_no_port, "parameters": input_parameters_ports} + results := violation with input as inp count(results) == 0 } test_input_with_hostnetwork_constraint_no_hostnetwork_not_allowed { - input := { "review": input_review_with_hostnetwork_no_port, "parameters": input_parameters_ports_no_hostnetwork} - results := violation with input as input + inp := { "review": input_review_with_hostnetwork_no_port, "parameters": input_parameters_ports_no_hostnetwork} + results := violation with input as inp count(results) > 0 } test_input_with_hostnetwork_constraint_no_hostnetwork_explicit { - input := { "review": input_review_no_hostnetwork_explicit, "parameters": input_parameters_ports_no_hostnetwork} - results := violation with input as input + inp := { "review": input_review_no_hostnetwork_explicit, "parameters": input_parameters_ports_no_hostnetwork} + results := violation with input as inp count(results) == 0 } test_input_with_hostnetwork_container_ports_not_allowed { - input := { "review": input_review_with_hostnetwork_port_outofrange, "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": input_review_with_hostnetwork_port_outofrange, "parameters": input_parameters_ports} + results := violation with input as inp count(results) == 1 } test_input_with_hostnetwork_container_ports_not_allowed_but_exempt { - input := { "review": input_review_with_hostnetwork_port_outofrange, "parameters": input_parameters_exempt} - results := violation with input as input + inp := { "review": input_review_with_hostnetwork_port_outofrange, "parameters": input_parameters_exempt} + results := violation with input as inp trace(sprintf("%v", [results])) count(results) == 0 } test_update { - input := { "review": object.union(input_review_no_hostnetwork_container_ports_outofrange, {"operation": "UPDATE"}), "parameters": input_parameters_ports} - results := violation with input as input + inp := { "review": object.union(input_review_no_hostnetwork_container_ports_outofrange, {"operation": "UPDATE"}), "parameters": input_parameters_ports} + results := violation with input as inp count(results) == 0 } @@ -172,7 +172,7 @@ input_parameters_ports_no_hostnetwork = { } input_parameters_exempt = { - "exemptImages": ["nginx"], + "exemptImages": ["nginx"], "hostNetwork": true, "min": 80, "max": 9000 diff --git a/src/pod-security-policy/privileged-containers/src_test.rego b/src/pod-security-policy/privileged-containers/src_test.rego index 4c1a462a2..c2b030e68 100644 --- a/src/pod-security-policy/privileged-containers/src_test.rego +++ b/src/pod-security-policy/privileged-containers/src_test.rego @@ -1,38 +1,38 @@ package k8spspprivileged test_input_container_not_privileged_allowed { - input := { "review": input_review} - results := violation with input as input + inp := { "review": input_review} + results := violation with input as inp count(results) == 0 } test_input_container_privileged_not_allowed { - input := { "review": input_review_priv} - results := violation with input as input + inp := { "review": input_review_priv} + results := violation with input as inp count(results) > 0 } test_input_container_many_not_privileged_allowed { - input := { "review": input_review_many} - results := violation with input as input + inp := { "review": input_review_many} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_privileged_not_allowed { - input := { "review": input_review_many_mixed} - results := violation with input as input + inp := { "review": input_review_many_mixed} + results := violation with input as inp count(results) > 0 } test_input_container_many_mixed_privileged_not_allowed_two { - input := { "review": input_review_many_mixed_two} - results := violation with input as input + inp := { "review": input_review_many_mixed_two} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_privileged_not_allowed_two_but_exempt { - input := { "review": input_review_many_mixed_two, "parameters": {"exemptImages": ["nginx"]}} - results := violation with input as input + inp := { "review": input_review_many_mixed_two, "parameters": {"exemptImages": ["nginx"]}} + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review_priv, {"operation": "UPDATE"})} - results := violation with input as input + inp := { "review": object.union(input_review_priv, {"operation": "UPDATE"})} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/proc-mount/constraint.tmpl b/src/pod-security-policy/proc-mount/constraint.tmpl index b06f815b6..9491d7b45 100644 --- a/src/pod-security-policy/proc-mount/constraint.tmpl +++ b/src/pod-security-policy/proc-mount/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspprocmount annotations: metadata.gatekeeper.sh/title: "Proc Mount" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.0.3 description: >- Controls the allowed `procMount` types for the container. Corresponds to the `allowedProcMountTypes` field in a PodSecurityPolicy. For more diff --git a/src/pod-security-policy/proc-mount/src.rego b/src/pod-security-policy/proc-mount/src.rego index cf501c8bd..222b5caca 100644 --- a/src/pod-security-policy/proc-mount/src.rego +++ b/src/pod-security-policy/proc-mount/src.rego @@ -18,7 +18,7 @@ input_proc_mount_type_allowed(allowedProcMount, c) { allowedProcMount == "default" lower(c.securityContext.procMount) == "default" } -input_proc_mount_type_allowed(allowedProcMount, c) { +input_proc_mount_type_allowed(allowedProcMount, _) { allowedProcMount == "unmasked" } diff --git a/src/pod-security-policy/proc-mount/src_test.rego b/src/pod-security-policy/proc-mount/src_test.rego index 32452d8fb..c72c404d0 100644 --- a/src/pod-security-policy/proc-mount/src_test.rego +++ b/src/pod-security-policy/proc-mount/src_test.rego @@ -1,73 +1,73 @@ package k8spspprocmount test_input_container_not_proc_mount_allowed { - input := { "review": input_review, "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_default} + results := violation with input as inp count(results) == 0 } test_input_container_proc_mount_not_allowed { - input := { "review": input_review_unmasked, "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": input_review_unmasked, "parameters": input_parameters_default} + results := violation with input as inp count(results) == 1 } test_input_container_proc_mount_not_allowed_null_param { - input := { "review": input_review_unmasked, "parameters": null } - results := violation with input as input + inp := { "review": input_review_unmasked, "parameters": null } + results := violation with input as inp count(results) == 1 } test_input_container_proc_mount_not_allowed_missing_param { - input := { "review": input_review_unmasked } - results := violation with input as input + inp := { "review": input_review_unmasked } + results := violation with input as inp count(results) == 1 } test_input_container_many_not_proc_mount_allowed { - input := { "review": input_review_many, "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_default} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_proc_mount_not_allowed { - input := { "review": input_review_many_mixed, "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": input_review_many_mixed, "parameters": input_parameters_default} + results := violation with input as inp count(results) == 1 } test_input_container_many_mixed_proc_mount_not_allowed_two { - input := { "review": input_review_many_mixed_two, "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": input_review_many_mixed_two, "parameters": input_parameters_default} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_proc_mount_not_allowed_two_but_exempt { - input := { "review": input_review_many_mixed_two, "parameters": input_parameters_exempt} - results := violation with input as input + inp := { "review": input_review_many_mixed_two, "parameters": input_parameters_exempt} + results := violation with input as inp count(results) == 0 } test_input_container_proc_mount_case_insensitive { - input := { "review": input_review, "parameters": input_parameters_default_lower} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_default_lower} + results := violation with input as inp count(results) == 0 } test_input_container_proc_mount_case_invalid_procMount { - input := { "review": input_review, "parameters": input_parameters_invalid_procMount} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_invalid_procMount} + results := violation with input as inp count(results) == 0 } test_input_container_not_proc_mount_unmasked { - input := { "review": input_review, "parameters": input_parameters_unmasked} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_unmasked} + results := violation with input as inp count(results) == 0 } test_input_container_proc_mount_unmasked { - input := { "review": input_review_unmasked, "parameters": input_parameters_unmasked} - results := violation with input as input + inp := { "review": input_review_unmasked, "parameters": input_parameters_unmasked} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_proc_mount_allowed_two { - input := { "review": input_review_many_mixed_two, "parameters": input_parameters_unmasked} - results := violation with input as input + inp := { "review": input_review_many_mixed_two, "parameters": input_parameters_unmasked} + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review_unmasked, {"operation": "UPDATE"}), "parameters": input_parameters_default} - results := violation with input as input + inp := { "review": object.union(input_review_unmasked, {"operation": "UPDATE"}), "parameters": input_parameters_default} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/read-only-root-filesystem/src_test.rego b/src/pod-security-policy/read-only-root-filesystem/src_test.rego index 348613859..d39073043 100644 --- a/src/pod-security-policy/read-only-root-filesystem/src_test.rego +++ b/src/pod-security-policy/read-only-root-filesystem/src_test.rego @@ -1,33 +1,33 @@ package k8spspreadonlyrootfilesystem test_input_container_not_readonlyrootfilesystem_allowed { - input := { "review": input_review} - results := violation with input as input + inp := { "review": input_review} + results := violation with input as inp count(results) == 1 } test_input_container_readonlyrootfilesystem_not_allowed { - input := { "review": input_review_ro} - results := violation with input as input + inp := { "review": input_review_ro} + results := violation with input as inp count(results) == 0 } test_input_container_many_mixed_readonlyrootfilesystem_not_allowed { - input := { "review": input_review_many_mixed} - results := violation with input as input + inp := { "review": input_review_many_mixed} + results := violation with input as inp count(results) == 2 } test_input_container_many_mixed_readonlyrootfilesystem_not_allowed_two { - input := { "review": input_review_many_mixed_two} - results := violation with input as input + inp := { "review": input_review_many_mixed_two} + results := violation with input as inp count(results) == 3 } test_input_container_many_mixed_readonlyrootfilesystem_not_allowed_two_but_exempt { - input := { "review": input_review_many_mixed_two, "parameters": {"exemptImages": ["nginx"]} } - results := violation with input as input + inp := { "review": input_review_many_mixed_two, "parameters": {"exemptImages": ["nginx"]} } + results := violation with input as inp count(results) == 0 } test_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"})} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"})} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/seccomp/constraint.tmpl b/src/pod-security-policy/seccomp/constraint.tmpl index c350e216a..7a5c95538 100644 --- a/src/pod-security-policy/seccomp/constraint.tmpl +++ b/src/pod-security-policy/seccomp/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspseccomp annotations: metadata.gatekeeper.sh/title: "Seccomp" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Controls the seccomp profile used by containers. Corresponds to the `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on diff --git a/src/pod-security-policy/seccomp/src.rego b/src/pod-security-policy/seccomp/src.rego index 53355d31a..61185ddb9 100644 --- a/src/pod-security-policy/seccomp/src.rego +++ b/src/pod-security-policy/seccomp/src.rego @@ -28,7 +28,7 @@ violation[{"msg": msg}] { msg := get_message(result.profile, result.file, name, result.location, allowed_profiles) } -get_message(profile, file, name, location, allowed_profiles) = message { +get_message(profile, _, name, location, allowed_profiles) = message { not profile == "Localhost" message := sprintf("Seccomp profile '%v' is not allowed for container '%v'. Found at: %v. Allowed profiles: %v", [profile, name, location, allowed_profiles]) } @@ -51,7 +51,7 @@ input_wildcard_allowed_files { } # Simple allowed Profiles -allowed_profile(profile, file, allowed) { +allowed_profile(profile, _, allowed) { not startswith(lower(profile), "localhost") profile == allowed[_] } @@ -66,20 +66,20 @@ allowed_profile(profile, file, allowed) { } # seccomp Localhost with wildcard -allowed_profile(profile, file, allowed) { +allowed_profile(profile, _, allowed) { profile == "Localhost" input_wildcard_allowed_files profile == allowed[_] } # annotation localhost with wildcard -allowed_profile(profile, file, allowed) { +allowed_profile(profile, _, allowed) { "localhost/*" == allowed[_] startswith(profile, "localhost/") } # annotation localhost without wildcard -allowed_profile(profile, file, allowed) { +allowed_profile(profile, _, allowed) { startswith(profile, "localhost/") profile == allowed[_] } diff --git a/src/pod-security-policy/seccomp/src_test.rego b/src/pod-security-policy/seccomp/src_test.rego index e2b32401a..161afa359 100644 --- a/src/pod-security-policy/seccomp/src_test.rego +++ b/src/pod-security-policy/seccomp/src_test.rego @@ -2,463 +2,463 @@ package k8spspseccomp # Annotation based seccomp with containers test_input_annotation_seccomp_empty_parameters { - input := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_empty} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_allowed_all { - input := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_allowed_in_list { - input := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_not_allowed_not_in_list { - input := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, single_container, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_pod_multiple_empty_parameters { - input := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_empty} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 2 } test_input_annotation_seccomp_pod_multiple_allowed_all { - input := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_multiple_allowed_in_list { - input := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_multiple_not_allowed_not_in_list { - input := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_annotation_seccomp_container_allowed_all { - input := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_container_allowed_in_list { - input := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_container_not_allowed_not_in_list { - input := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_containers_allowed_in_list { - input := {"review": get_object(container_annotations, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotations, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_containers_not_allowed_not_in_list { - input := {"review": get_object(container_annotations, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotations, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_annotation_seccomp_containers_mixed { - input := {"review": get_object(container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_containers_mixed_missing { - input := {"review": get_object(container_annotation, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_containers_allowed_in_list_multiple { - input := {"review": get_object(container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_container { - input := {"review": get_object(pod_container_annotations, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_container_not_allowed { - input := {"review": get_object(pod_container_annotations, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_annotation_seccomp_pod_container_both_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_container_mixed_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_pod_container_mixed_not_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_annotation_seccomp_pod_container_both_allowed_reversed { - input := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_container_mixed_allowed_reversed { - input := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_pod_container_mixed_not_allowed_reversed { - input := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed_rev, {}, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } # Annotation based seccomp with init containers test_input_annotation_seccomp_pod_initcontainer_both_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_annotation_seccomp_pod_initcontainer_mixed_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_annotation_seccomp_pod_initcontainer_mixed_not_allowed { - input := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_container_annotations_mixed, {}, {}, multiple_containers), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } # securityContext based seccomp with containers test_input_seccomp_empty_parameters { - input := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_empty} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_seccomp_allowed_all { - input := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccomp_allowed_in_list { - input := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_not_allowed_not_in_list { - input := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_pod_multiple_empty_parameters { - input := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_empty} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 2 } test_input_seccomp_pod_multiple_allowed_all { - input := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_multiple_allowed_in_list { - input := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_multiple_not_allowed_not_in_list { - input := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_seccomp_pod_localhost_allowed_wrong_file { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc} + results := violation with input as inp count(results) == 1 } test_input_seccomp_pod_localhost_allowed_no_specified_file { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc_localhost_no_file} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc_localhost_no_file} + results := violation with input as inp count(results) == 1 } test_input_seccomp_pod_localhost_allowed_wildcard_file { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc_localhost_wildcard_file} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_sc_localhost_wildcard_file} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_localhost_allowed_annotation_wildcard_file { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_localhost_wildcard} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_localhost_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_localhost_allowed_both_wildcard_file { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_localhost_wildcard_both} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_localhost_wildcard_both} + results := violation with input as inp count(results) == 0 } test_input_seccomp_not_allowed_not_configured { - input := {"review": get_object({}, {}, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_not_allowed_multiple_not_configured { - input := {"review": get_object({}, {}, multiple_containers, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 2 } test_input_seccomp_container_allowed_all { - input := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_wildcard} - results := violation with input as input + inp := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_seccomp_container_allowed_in_list { - input := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_container_not_allowed_not_in_list { - input := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_containers_allowed_in_list { - input := {"review": get_object({}, {}, multiple_containers_sc, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers_sc, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_containers_not_allowed_not_in_list { - input := {"review": get_object({}, {}, multiple_containers_sc, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers_sc, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_seccomp_containers_mixed { - input := {"review": get_object({}, {}, multiple_containers_sc_mixed, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers_sc_mixed, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_containers_mixed_missing { - input := {"review": get_object({}, {}, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_containers_allowed_in_list_multiple { - input := {"review": get_object({}, {}, multiple_containers_sc_mixed, {}), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object({}, {}, multiple_containers_sc_mixed, {}), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_container { - input := {"review": get_object({}, context_runtimedefault, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_container_mixed_not_allowed_but_exempt { - input := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_exempt} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, single_container, {}), "parameters": input_parameters_exempt} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_container_not_allowed { - input := {"review": get_object({}, context_runtimedefault, multiple_containers_sc_missing, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_runtimedefault, multiple_containers_sc_missing, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_seccomp_pod_container_both_allowed { - input := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_container_mixed_allowed { - input := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_pod_container_mixed_not_allowed { - input := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, multiple_containers_sc_missing, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } # securityContext based seccomp with init containers test_input_seccomp_pod_initcontainer_both_allowed { - input := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameters_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seccomp_pod_initcontainer_mixed_allowed { - input := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } test_input_seccomp_pod_initcontainer_mixed_not_allowed { - input := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, {}, multiple_containers_sc_missing), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } # Both annotation and securityContext based seccomp mixed test_input_both_seccomp_pod_context_container_annotation { - input := {"review": get_object(container_annotation_unconfined, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation_unconfined, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_both_seccomp_pod_annotation_container_context { - input := {"review": get_object(pod_annotation_unconfined, {}, single_container_sc, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation_unconfined, {}, single_container_sc, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_both_seccomp_pod_context_and_annotation { - input := {"review": get_object(pod_annotation, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, context_runtimedefault, single_container, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_both_seccomp_container_context_and_annotation { - input := {"review": get_object(container_annotation, {}, single_container_sc, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container_sc, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 0 } test_input_both_seccomp_pod_context_container_annotation_not_allowed { - input := {"review": get_object(container_annotation_unconfined, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation_unconfined, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_both_seccomp_pod_annotation_container_context_not_allowed { - input := {"review": get_object(pod_annotation_unconfined, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation_unconfined, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_both_seccomp_pod_context_and_annotation_not_allowed { - input := {"review": get_object(pod_annotation, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(pod_annotation, context_runtimedefault, single_container, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_both_seccomp_container_context_and_annotation_not_allowed { - input := {"review": get_object(container_annotation, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container_sc, {}), "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_both_seccomp_pod_context_container_annotation_multiple_mixed { - input := {"review": get_object(container_annotation, context_unconfined, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} - results := violation with input as input + inp := {"review": get_object(container_annotation, context_unconfined, multiple_containers_sc_missing, {}), "parameters": input_parameter_in_list} + results := violation with input as inp count(results) == 1 } # Testing translation between annotation and securityContext test_translation_seccomp_allowed_annotation_all { - input := {"parameters": input_parameters_annotation} - output := get_allowed_profiles with input as input + inp := {"parameters": input_parameters_annotation} + output := get_allowed_profiles with input as inp output == allowed_full_translated } test_translation_seccomp_allowed_context_all { - input := {"parameters": input_parameters_sc} - output := get_allowed_profiles with input as input + inp := {"parameters": input_parameters_sc} + output := get_allowed_profiles with input as inp output == allowed_full_translated } test_translation_seccomp_allowed_context_localhost_wildcard_file { - input := {"parameters": input_parameters_sc_localhost_wildcard_file} - output := get_allowed_profiles with input as input + inp := {"parameters": input_parameters_sc_localhost_wildcard_file} + output := get_allowed_profiles with input as inp output == {"Localhost", "localhost/*"} } test_translation_seccomp_allowed_context_localhost_no_file { - input := {"parameters": input_parameters_sc_localhost_no_file} - output := get_allowed_profiles with input as input + inp := {"parameters": input_parameters_sc_localhost_no_file} + output := get_allowed_profiles with input as inp output == {"Localhost"} } test_input_translation_seccomp_annotation_match_allowed_context { - input := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_sc} - results := violation with input as input + inp := {"review": get_object(container_annotation, {}, single_container, {}), "parameters": input_parameters_sc} + results := violation with input as inp count(results) == 0 } test_input_translation_seccomp_context_match_allowed_annotation { - input := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_annotation} - results := violation with input as input + inp := {"review": get_object({}, {}, single_container_sc, {}), "parameters": input_parameters_annotation} + results := violation with input as inp count(results) == 0 } test_input_translation_seccomp_context_localhost_allowed_annotation { - input := {"review": get_object({}, context_localhost1, single_container, {}), "parameters": input_parameters_annotation} - results := violation with input as input + inp := {"review": get_object({}, context_localhost1, single_container, {}), "parameters": input_parameters_annotation} + results := violation with input as inp count(results) == 0 } test_input_translation_seccomp_context_localhost_allowed_annotation_missing { - input := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_annotation} - results := violation with input as input + inp := {"review": get_object({}, context_localhost, single_container, {}), "parameters": input_parameters_annotation} + results := violation with input as inp count(results) == 1 } diff --git a/src/pod-security-policy/selinux/constraint.tmpl b/src/pod-security-policy/selinux/constraint.tmpl index 051b9c694..25da7db59 100644 --- a/src/pod-security-policy/selinux/constraint.tmpl +++ b/src/pod-security-policy/selinux/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspselinuxv2 annotations: metadata.gatekeeper.sh/title: "SELinux V2" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Defines an allow-list of seLinuxOptions configurations for pod containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. diff --git a/src/pod-security-policy/selinux/src.rego b/src/pod-security-policy/selinux/src.rego index f11ededb9..0e6873bea 100644 --- a/src/pod-security-policy/selinux/src.rego +++ b/src/pod-security-policy/selinux/src.rego @@ -35,7 +35,7 @@ input_seLinuxOptions_allowed(options) { field_allowed(field, options, params) { params[field] == options[field] } -field_allowed(field, options, params) { +field_allowed(field, options, _) { not has_field(options, field) } diff --git a/src/pod-security-policy/selinux/src_test.rego b/src/pod-security-policy/selinux/src_test.rego index 8d796e8c7..6b0c4c739 100644 --- a/src/pod-security-policy/selinux/src_test.rego +++ b/src/pod-security-policy/selinux/src_test.rego @@ -1,141 +1,141 @@ package k8spspselinux test_input_seLinux_options_allowed_in_list { - input := { "review": input_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_allowed_in_list_subset { - input := { "review": input_review, "parameters": input_parameters_in_list_subset} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_subset} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_allowed_in_list_split_list { - input := { "review": input_review, "parameters": input_parameters_in_list_split_two} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_split_two} + results := violation with input as inp count(results) == 1 } test_input_seLinux_option_not_allowed_not_in_list { - input := { "review": input_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_empty { - input := { "review": input_review, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_seLinux_option_two_empty { - input := { "review": input_review_two , "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_two , "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_no_security_context { - input := { "review": input_review_no_security_context, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_no_security_context, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_two_allowed_in_list { - input := { "review": input_review_two, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_two, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_two_subset_allowed_in_list { - input := { "review": input_review_two_subset, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_two_subset, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_subset_allowed_in_list_subset { - input := { "review": input_review_two_subset, "parameters": input_parameters_in_list_subset} - results := violation with input as input + inp := { "review": input_review_two_subset, "parameters": input_parameters_in_list_subset} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_subset_allowed_in_list_split_subset { - input := { "review": input_review_two_subset, "parameters": input_parameters_in_list_split_subset} - results := violation with input as input + inp := { "review": input_review_two_subset, "parameters": input_parameters_in_list_split_subset} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_allowed_in_list_split_subset { - input := { "review": input_review, "parameters": input_parameters_in_list_split_subset} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list_split_subset} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_two_subset_not_allowed_not_in_list { - input := { "review": input_review_two_subset, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_two_subset, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seLinux_option_two_not_allowed_not_in_list { - input := { "review": input_review_two, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_two, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_many_allowed_in_list { - input := { "review": input_review_many, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_many_not_allowed_not_in_list { - input := { "review": input_review_many, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_many_not_allowed_not_in_list_but_exempt { - input := { "review": input_review_many, "parameters": input_parameters_exempt} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_exempt} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_many_not_allowed_not_in_list_two { - input := { "review": input_review_many, "parameters": input_parameters_not_in_list_two} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_not_in_list_two} + results := violation with input as inp count(results) == 1 } test_input_seLinux_option_two_allowed_in_list_subset { - input := { "review": input_review_two , "parameters": input_parameters_in_list_subset} - results := violation with input as input + inp := { "review": input_review_two , "parameters": input_parameters_in_list_subset} + results := violation with input as inp count(results) == 1 } test_input_seLinux_option_two_not_allowed_not_in_list_subset { - input := { "review": input_review_two , "parameters": input_parameters_not_in_list_two} - results := violation with input as input + inp := { "review": input_review_two , "parameters": input_parameters_not_in_list_two} + results := violation with input as inp count(results) == 1 } test_input_seLinux_options_many_allowed_in_list_double_seccontext { - input := { "review": input_review_many_double_seccontext, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many_double_seccontext, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_seLinux_options_many_not_allowed_not_in_list_double_seccontext { - input := { "review": input_review_many_double_seccontext, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many_double_seccontext, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 3 } test_input_seLinux_options_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_in_list_subset} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_in_list_subset} + results := violation with input as inp count(results) == 0 } diff --git a/src/pod-security-policy/users/constraint.tmpl b/src/pod-security-policy/users/constraint.tmpl index 2c503e343..29523b763 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.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and diff --git a/src/pod-security-policy/users/src.rego b/src/pod-security-policy/users/src.rego index 4d28bafd2..decf44cf6 100644 --- a/src/pod-security-policy/users/src.rego +++ b/src/pod-security-policy/users/src.rego @@ -47,11 +47,11 @@ get_user_violation(params, container) = msg { msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) } -accept_users("RunAsAny", provided_user) {true} +accept_users("RunAsAny", _) -accept_users("MustRunAsNonRoot", provided_user) = res {res := provided_user != 0} +accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 -accept_users("MustRunAs", provided_user) = res { +accept_users("MustRunAs", provided_user) := res { ranges := input.parameters.runAsUser.ranges res := is_in_range(provided_user, ranges) } @@ -80,18 +80,15 @@ get_violation(field, params, container) = msg { msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) } -accept_value("RunAsAny", provided_value, ranges) {true} +accept_value("RunAsAny", _, _) -accept_value("MayRunAs", provided_value, ranges) = res { res := is_in_range(provided_value, ranges)} +accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) -accept_value("MustRunAs", provided_value, ranges) = res { res := 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, review) = out { - container_value := get_seccontext_field(field, container) - out := container_value -} +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 { diff --git a/src/pod-security-policy/users/src_test.rego b/src/pod-security-policy/users/src_test.rego index 6e5979c87..9c8c5e04f 100644 --- a/src/pod-security-policy/users/src_test.rego +++ b/src/pod-security-policy/users/src_test.rego @@ -39,431 +39,431 @@ package k8spspallowedusers ## RunAsUser ## test_user_one_container_run_as_rule_any { - input := { "review": review(null, [ctr("cont1", runAsUser(12))], null), "parameters": user_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(12))], null), "parameters": user_runasany } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_as_rule_any_root_user { - input := { "review": review(null, [ctr("cont1", runAsUser(0))], null), "parameters": user_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(0))], null), "parameters": user_runasany } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_as_rule_non_root_user_is_not_root { - input := { "review": review(null, [ctr("cont1", runAsUser(1))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(1))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_as_rule_non_root_user_is_root { - input := { "review": review(null, [ctr("cont1", runAsUser(0))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(0))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_as_rule_non_root_seccont_runasnonroot_user_is_not_defined { - input := { "review": review(null, [ctr("cont1", runAsNonRoot(true))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsNonRoot(true))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_as_rule_non_root_seccont_runasnonroot_user_is_root { - input := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(true),runAsUser(0)))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(true),runAsUser(0)))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_as_rule_non_root_seccont_runasnonroot_user_is_not_root { - input := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(true),runAsUser(10)))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(true),runAsUser(10)))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_as_rule_non_root_seccont_runasnonroot_is_false_user_is_not_defined { - input := { "review": review(null, [ctr("cont1", runAsNonRoot(false))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsNonRoot(false))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_as_rule_non_root_seccont_runasnonroot_is_false_user_is_not_root { - input := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(false),runAsUser(10)))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", object.union(runAsNonRoot(false),runAsUser(10)))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_in_range_user_in_range { - input := { "review": review(null, [ctr("cont1", runAsUser(150))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(150))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_in_range_user_out_of_range { - input := { "review": review(null, [ctr("cont1", runAsUser(10))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(10))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_in_range_user_lower_edge_of_range { - input := { "review": review(null, [ctr("cont1", runAsUser(100))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(100))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_in_range_user_upper_edge_of_range { - input := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_user_one_container_run_in_range_seccont_runasnonroot { - input := { "review": review(null, [ctr("cont1", runAsNonRoot(true))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsNonRoot(true))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_in_range_user_between_ranges { - input := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": user_mustrunas_two_ranges } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": user_mustrunas_two_ranges } + results := violation with input as inp count(results) == 1 } test_user_one_container_run_in_range_user_between_ranges_but_exempt { - input := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": object.union(user_mustrunas_two_ranges, {"exemptImages": ["nginx"]}) } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsUser(200))], null), "parameters": object.union(user_mustrunas_two_ranges, {"exemptImages": ["nginx"]}) } + results := violation with input as inp count(results) == 0 } test_non_root_container_pod_conflict { - input := {"review": review({"runAsNonRoot": true}, [ctr("cont1", runAsNonRoot(false))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + inp := {"review": review({"runAsNonRoot": true}, [ctr("cont1", runAsNonRoot(false))], null), "parameters": user_mustrunasnonroot } + results := violation with input as inp count(results) == 1 } test_user_two_containers_run_as_rule_any { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(1)), ctr("cont2", runAsUser(100))], null), "parameters": user_runasany } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_two_containers_run_as_rule_non_root_users_are_not_root { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(1)), ctr("cont2", runAsUser(100))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_two_containers_run_as_rule_non_root_one_is_root { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(1)), ctr("cont2", runAsUser(0))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_user_two_containers_run_as_rule_non_root_one_seccont_runasnonroot { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(1)), ctr("cont2", runAsNonRoot(true))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_two_containers_run_as_rule_non_root_one_root_other_has_seccont_runasnonroot { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(0)), ctr("cont2", runAsNonRoot(true))], null), "parameters": user_mustrunasnonroot } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_user_two_containers_run_in_range_both_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(150)), ctr("cont2", runAsUser(103))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_two_containers_run_in_range_one_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(150)), ctr("cont2", runAsUser(13))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_user_two_containers_run_in_range_neither_in_range_two_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(150)), ctr("cont2", runAsUser(130))], null), "parameters": user_mustrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_user_one_container_one_initcontainer_run_in_range_user_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(150))], [ctr("init1", runAsUser(150))]), "parameters": user_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_one_container_one_initcontainer_run_in_range_user_not_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(150))], [ctr("init1", runAsUser(250))]), "parameters": user_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_user_one_container_empty_security_context { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_no_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_no_security_context_RunAsAny { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_runasany } + results := violation with input as inp count(results) == 0 } test_user_one_container_empty_security_context_empty_pod_security_context { - input := { "review": review({}, [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review({}, [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_no_security_context_no_pod_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_pod_defined_null_container_run_in_range_user_in_range { - input := { "review": review(runAsUser(150), [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(runAsUser(150), [ctr("cont1", null)], null), "parameters": user_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_user_one_container_pod_defined_run_in_range_user_in_range { - input := { "review": review(runAsUser(150), [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(runAsUser(150), [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_user_one_container_pod_defined_run_in_range_user_not_in_range { - input := { "review": review(runAsUser(250), [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsUser(250), [ctr("cont1", {})], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_one_container_pod_defined_run_in_range_container_overrides_user_in_range { - input := { "review": review(runAsUser(250), [ctr("cont1", runAsUser(150))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsUser(250), [ctr("cont1", runAsUser(150))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_user_one_container_pod_defined_run_in_range_container_overrides_user_not_in_range { - input := { "review": review(runAsUser(150), [ctr("cont1", runAsUser(250))], null), "parameters": user_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsUser(150), [ctr("cont1", runAsUser(250))], null), "parameters": user_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_user_input_container_run_as_rule_any_ignore_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(10))], null), "parameters": runAsUser(rule("RunAsAny", [range(100, 200)])) } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_input_container_run_as_rule_non_root_ignore_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsUser(10))], null), "parameters": runAsUser(rule("MustRunAsNonRoot", [range(100, 200)])) } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_user_input_container_run_as_rule_non_root_seccont_runasnonroot_ignore_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsNonRoot(true))], null), "parameters": runAsUser(rule("MustRunAsNonRoot", [range(100, 200)])) } - results := violation with input as input + results := violation with input as inp count(results) == 0 } ## runAsGroup ## test_group_one_container_run_as_rule_any { - input := { "review": review(null, [ctr("cont1", runAsGroup(12))], null), "parameters": group_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(12))], null), "parameters": group_runasany } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_as_rule_any_root_user { - input := { "review": review(null, [ctr("cont1", runAsGroup(0))], null), "parameters": group_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(0))], null), "parameters": group_runasany } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_in_range { - input := { "review": review(null, [ctr("cont1", runAsGroup(150))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(150))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_out_of_range { - input := { "review": review(null, [ctr("cont1", runAsGroup(10))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(10))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_run_in_range_user_lower_edge_of_range { - input := { "review": review(null, [ctr("cont1", runAsGroup(100))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(100))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_upper_edge_of_range { - input := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_between_ranges { - input := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mustrunas_two_ranges } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mustrunas_two_ranges } + results := violation with input as inp count(results) == 1 } test_group_two_containers_run_as_rule_any { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(1)), ctr("cont2", runAsGroup(100))], null), "parameters": group_runasany } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_group_two_containers_run_in_range_both_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150)), ctr("cont2", runAsGroup(103))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_group_two_containers_run_in_range_one_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150)), ctr("cont2", runAsGroup(13))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_group_two_containers_run_in_range_neither_in_range_two_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150)), ctr("cont2", runAsGroup(130))], null), "parameters": group_mustrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_group_one_container_one_initcontainer_run_in_range_user_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150))], [ctr("init1", runAsGroup(150))]), "parameters": group_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_group_one_container_one_initcontainer_run_in_range_user_not_in_range { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150))], [ctr("init1", runAsGroup(250))]), "parameters": group_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_group_one_container_empty_security_context { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_no_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_no_security_context_RunAsAny { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_runasany } + results := violation with input as inp count(results) == 0 } test_group_one_container_empty_security_context_empty_pod_security_context { - input := { "review": review({}, [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review({}, [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_no_security_context_no_pod_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_pod_defined_null_container_run_in_range_user_in_range { - input := { "review": review(runAsGroup(150), [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(runAsGroup(150), [ctr("cont1", null)], null), "parameters": group_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_group_one_container_pod_defined_run_in_range_user_in_range { - input := { "review": review(runAsGroup(150), [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(runAsGroup(150), [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_group_one_container_pod_defined_run_in_range_user_not_in_range { - input := { "review": review(runAsGroup(250), [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsGroup(250), [ctr("cont1", {})], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_pod_defined_run_in_range_container_overrides_user_in_range { - input := { "review": review(runAsGroup(250), [ctr("cont1", runAsGroup(150))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsGroup(250), [ctr("cont1", runAsGroup(150))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_pod_defined_run_in_range_container_overrides_user_not_in_range { - input := { "review": review(runAsGroup(150), [ctr("cont1", runAsGroup(250))], null), "parameters": group_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsGroup(150), [ctr("cont1", runAsGroup(250))], null), "parameters": group_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_input_container_run_as_rule_any_ignore_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(10))], null), "parameters": runAsGroup(rule("RunAsAny", [range(100, 200)])) } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_group_one_container_empty_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_no_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_in_range_mayrun { - input := { "review": review(null, [ctr("cont1", runAsGroup(150))], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(150))], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_run_in_range_user_out_of_range_mayrun { - input := { "review": review(null, [ctr("cont1", runAsGroup(10))], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(10))], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_group_one_container_run_in_range_user_between_ranges_mayrun { - input := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mayrunas_two_ranges } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", runAsGroup(200))], null), "parameters": group_mayrunas_two_ranges } + results := violation with input as inp count(results) == 1 } test_group_two_containers_run_in_range_neither_in_range_two_ranges_mayrun { - input := { + inp := { "review": review(null, [ctr("cont1", runAsGroup(150)), ctr("cont2", runAsGroup(130))], null), "parameters": group_mayrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_group_one_container_pod_defined_run_in_range_container_overrides_user_in_range_mayrun { - input := { "review": review(runAsGroup(250), [ctr("cont1", runAsGroup(150))], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsGroup(250), [ctr("cont1", runAsGroup(150))], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_group_one_container_pod_defined_run_in_range_container_overrides_user_not_in_range_mayrun { - input := { "review": review(runAsGroup(150), [ctr("cont1", runAsGroup(250))], null), "parameters": group_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(runAsGroup(150), [ctr("cont1", runAsGroup(250))], null), "parameters": group_mayrunas_100_200 } + results := violation with input as inp count(results) == 1 } @@ -471,134 +471,134 @@ test_group_one_container_pod_defined_run_in_range_container_overrides_user_not_i ## supplementalGroups ## test_supplemental_two_containers_run_as_rule_any { - input := { + inp := { "review": review(supplementalGroups([15]), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": supplemental_runasany } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_supplemental_two_containers_run_in_range_both_in_range { - input := { + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_supplemental_two_containers_run_in_range_neither_in_range_two_ranges { - input := { + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": supplemental_mustrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_supplemental_one_container_one_initcontainer_run_in_range_user_in_range { - input := { + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", null)], [ctr("init1", null)]), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_one_initcontainer_run_in_range_user_not_in_range { - input := { + inp := { "review": review(supplementalGroups([250]), [ctr("cont1", null)], [ctr("init1", null)]), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_supplemental_one_container_empty_security_context { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_no_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_no_security_context_RunAsAny { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_runasany } + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_empty_security_context_empty_pod_security_context { - input := { "review": review({}, [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review({}, [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_no_security_context_no_pod_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_pod_defined_null_container_run_in_range_user_in_range { - input := { "review": review(supplementalGroups([150]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_pod_defined_run_in_range_user_in_range { - input := { "review": review(supplementalGroups([150]), [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_pod_defined_run_in_range_user_not_in_range { - input := { "review": review(supplementalGroups([250]), [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(supplementalGroups([250]), [ctr("cont1", {})], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_pod_defined_run_in_range_container_overrides_user_in_range { - input := { "review": review(supplementalGroups([250]), [ctr("cont1", supplementalGroups(150))], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(supplementalGroups([250]), [ctr("cont1", supplementalGroups(150))], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_pod_defined_run_in_range_container_overrides_user_not_in_range { - input := { "review": review(supplementalGroups([150]), [ctr("cont1", supplementalGroups(250))], null), "parameters": supplemental_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(supplementalGroups([150]), [ctr("cont1", supplementalGroups(250))], null), "parameters": supplemental_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_supplemental_one_container_empty_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": supplemental_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": supplemental_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_no_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": supplemental_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_supplemental_two_containers_run_in_range_neither_in_range_mayrun { - input := { + inp := { "review": review(supplementalGroups([230]), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": supplemental_mayrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_supplemental_two_containers_run_in_range_both_in_range_mayrun { - input := { + inp := { "review": review(supplementalGroups([100]), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": supplemental_mayrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_run_in_range_two_ranges_both_in_range { - input := { "review": review(supplementalGroups([120, 180]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(supplementalGroups([120, 180]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_run_in_range_two_ranges_none_in_range { - input := { "review": review(supplementalGroups([120, 180]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(supplementalGroups([120, 180]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_supplemental_one_container_run_in_range_two_ranges_one_in_range { - input := { "review": review(supplementalGroups([150, 250]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(supplementalGroups([150, 250]), [ctr("cont1", null)], null), "parameters": supplemental_mustrunas_100_200} + results := violation with input as inp count(results) == 1 } @@ -606,111 +606,111 @@ test_supplemental_one_container_run_in_range_two_ranges_one_in_range { ## fsGroup ## test_fsgroup_two_containers_run_as_rule_any { - input := { + inp := { "review": review(fsGroup(15), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": fsgroup_runasany } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_fsgroup_two_containers_run_in_range_both_in_range { - input := { + inp := { "review": review(fsGroup(150), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_fsgroup_two_containers_run_in_range_neither_in_range_two_ranges { - input := { + inp := { "review": review(fsGroup(150), [ctr("cont1", null), ctr("cont2", null)], null), "parameters": fsgroup_mustrunas_two_ranges } - results := violation with input as input + results := violation with input as inp count(results) == 2 } test_fsgroup_one_container_one_initcontainer_run_in_range_user_in_range { - input := { + inp := { "review": review(fsGroup(150), [ctr("cont1", null)], [ctr("init1", null)]), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_one_initcontainer_run_in_range_user_not_in_range { - input := { + inp := { "review": review(fsGroup(250), null, [ctr("init1", null)]), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_empty_security_context { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_no_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_no_security_context_RunAsAny { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_runasany } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_runasany } + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_empty_security_context_empty_pod_security_context { - input := { "review": review({}, [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review({}, [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_no_security_context_no_pod_security_context { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_pod_defined_null_container_run_in_range_user_in_range { - input := { "review": review(fsGroup(150), [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(fsGroup(150), [ctr("cont1", null)], null), "parameters": fsgroup_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_pod_defined_run_in_range_user_in_range { - input := { "review": review(fsGroup(150), [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200} - results := violation with input as input + inp := { "review": review(fsGroup(150), [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200} + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_pod_defined_run_in_range_user_not_in_range { - input := { "review": review(fsGroup(250), [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(fsGroup(250), [ctr("cont1", {})], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_one_container_pod_defined_run_in_range_container_overrides_user_in_range { - input := { "review": review(fsGroup(250), [ctr("cont1", fsGroup(150))], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(fsGroup(250), [ctr("cont1", fsGroup(150))], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_pod_defined_run_in_range_container_overrides_user_not_in_range { - input := { "review": review(fsGroup(150), [ctr("cont1", fsGroup(250))], null), "parameters": fsgroup_mustrunas_100_200 } - results := violation with input as input + inp := { "review": review(fsGroup(150), [ctr("cont1", fsGroup(250))], null), "parameters": fsgroup_mustrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_fsgroup_input_container_run_as_rule_any_ignore_ranges { - input := { + inp := { "review": review(null, [ctr("cont1", fsGroup(10))], null), "parameters": fsGroup(rule("RunAsAny", [range(100, 200)])) } - results := violation with input as input + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_empty_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", {})], null), "parameters": fsgroup_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", {})], null), "parameters": fsgroup_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_fsgroup_one_container_no_security_context_mayrun { - input := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mayrunas_100_200 } - results := violation with input as input + inp := { "review": review(null, [ctr("cont1", null)], null), "parameters": fsgroup_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } @@ -718,103 +718,103 @@ test_fsgroup_one_container_no_security_context_mayrun { ## Mixed Functionality ## test_mixed_runAsAny_all_non_root { - input := {"review": review(run_as_rule(12, 30, [50], 101), [ctr("cont1", null)], null), "parameters": mixed_runasany } - results := violation with input as input + inp := {"review": review(run_as_rule(12, 30, [50], 101), [ctr("cont1", null)], null), "parameters": mixed_runasany } + results := violation with input as inp count(results) == 0 } test_mixed_runAsAny_all_root { - input := {"review": review(run_as_rule(0, 0, [0], 0), [ctr("cont1", null)], null), "parameters": mixed_runasany } - results := violation with input as input + inp := {"review": review(run_as_rule(0, 0, [0], 0), [ctr("cont1", null)], null), "parameters": mixed_runasany } + results := violation with input as inp count(results) == 0 } test_mixed_pod_level_all_defined_all_in_range_mustrun { - input := {"review": review(run_as_rule(150, 150, [150], 150), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(run_as_rule(150, 150, [150], 150), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_mixed_pod_level_all_defined_none_in_range_mustrun { - input := {"review": review(run_as_rule(250, 250, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(run_as_rule(250, 250, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 4 } test_mixed_pod_level_all_defined_mixed_in_range_mustrun { - input := {"review": review(run_as_rule(150, 150, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(run_as_rule(150, 150, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 2 } test_mixed_container_level_all_defined_all_in_range_mustrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, [150], 150))], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, [150], 150))], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_mixed_container_level_all_defined_none_in_range_mustrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(250, 250, [250], 250))], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(250, 250, [250], 250))], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 4 } test_mixed_container_level_all_defined_mixed_in_range_mustrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, [250], 250))], null), "parameters": mixed_mustrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, [250], 250))], null), "parameters": mixed_mustrunas_100_200 } + results := violation with input as inp count(results) == 2 } test_mixed_pod_level_all_defined_none_in_range_mayrun { - input := {"review": review(run_as_rule(250, 250, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mayrunas_100_200 } - results := violation with input as input + inp := {"review": review(run_as_rule(250, 250, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mayrunas_100_200 } + results := violation with input as inp count(results) == 3 } test_mixed_pod_level_all_defined_mixed_in_range_mayrun { - input := {"review": review(run_as_rule(150, 150, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mayrunas_100_200 } - results := violation with input as input + inp := {"review": review(run_as_rule(150, 150, [250], 250), [ctr("cont1", null)], null), "parameters": mixed_mayrunas_100_200 } + results := violation with input as inp count(results) == 2 } test_mixed_container_level_all_defined_all_in_range_mayrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_mayrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_mayrunas_100_200 } + results := violation with input as inp count(results) == 0 } test_mixed_container_level_all_defined_none_in_range_mayrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(250, 250, null, null))], null), "parameters": mixed_mayrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(250, 250, null, null))], null), "parameters": mixed_mayrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_mixed_container_level_all_defined_mixed_in_range_mayrun { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 250, null, null))], null), "parameters": mixed_mayrunas_100_200 } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 250, null, null))], null), "parameters": mixed_mayrunas_100_200 } + results := violation with input as inp count(results) == 1 } test_mixed_pod_level_all_defined_none_in_range_mixed_rules { - input := {"review": review(run_as_rule(0, 0, 250, 250), [ctr("cont1", null)], null), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": review(run_as_rule(0, 0, 250, 250), [ctr("cont1", null)], null), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 3 } # violation from MustRunAs SupplementalGroups and MayRunAs FSGroup, range within 100&200 test_mixed_pod_level_all_defined_mixed_in_range_mixed_rules { - input := {"review": review(run_as_rule(150, 150, 250, 250), [ctr("cont1", null)], null), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": review(run_as_rule(150, 150, 250, 250), [ctr("cont1", null)], null), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 2 } # violation from no MustRunAs SupplementalGroups defined (can't define on container level) test_mixed_container_level_all_defined_all_in_range_mixed_rules { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 1 } # violation from MustRunAsNonRoot RunAsUser rule, and no MustRunAs SupplementalGroups defined (can't define on container level) test_mixed_container_level_all_defined_none_in_range_mixed_rules { - input := {"review": review(null, [ctr("cont1", run_as_rule(0, 0, null, null))], null), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(0, 0, null, null))], null), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 2 } # violation from no MustRunAs SupplementalGroups defined (can't define on container level) test_mixed_container_level_all_defined_mixed_in_range_mixed_rules { - input := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 1 } test_update { - input := {"review": object.union(review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), {"operation": "UPDATE"}), "parameters": mixed_all_rules } - results := violation with input as input + inp := {"review": object.union(review(null, [ctr("cont1", run_as_rule(150, 150, null, null))], null), {"operation": "UPDATE"}), "parameters": mixed_all_rules } + results := violation with input as inp count(results) == 0 } @@ -866,13 +866,12 @@ run_as_rule(user, group, supplemental, fsgroup) = out { out = object.union(object.union(user_obj, group_obj), object.union(supplemental_obj, fsgroup_obj)) } -obj_if_exists(key, val) = out { - not is_null(val) - out := { key: val } +obj_if_exists(key, val) = {key: val} { + not is_null(val) } -obj_if_exists(key, val) = out { - is_null(val) - out := {} + +obj_if_exists(_, val) := {} { + is_null(val) } # Parameters diff --git a/src/pod-security-policy/volumes/constraint.tmpl b/src/pod-security-policy/volumes/constraint.tmpl index 40f87e2c3..0fe0567fe 100644 --- a/src/pod-security-policy/volumes/constraint.tmpl +++ b/src/pod-security-policy/volumes/constraint.tmpl @@ -4,7 +4,7 @@ metadata: name: k8spspvolumetypes annotations: metadata.gatekeeper.sh/title: "Volume Types" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Restricts mountable volume types to those specified by the user. Corresponds to the `volumes` field in a PodSecurityPolicy. For more diff --git a/src/pod-security-policy/volumes/src.rego b/src/pod-security-policy/volumes/src.rego index 2d10ecf3e..389e48a44 100644 --- a/src/pod-security-policy/volumes/src.rego +++ b/src/pod-security-policy/volumes/src.rego @@ -13,7 +13,7 @@ violation[{"msg": msg, "details": {}}] { } # * may be used to allow all volume types -input_volume_type_allowed(field) { +input_volume_type_allowed(_) { input.parameters.volumes[_] == "*" } diff --git a/src/pod-security-policy/volumes/src_test.rego b/src/pod-security-policy/volumes/src_test.rego index 841e79bf8..6d38babcf 100644 --- a/src/pod-security-policy/volumes/src_test.rego +++ b/src/pod-security-policy/volumes/src_test.rego @@ -1,75 +1,75 @@ package k8spspvolumetypes test_input_volume_type_allowed_all { - input := { "review": input_review, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_volume_type_allowed_all_many_volumes { - input := { "review": input_review_many, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_volume_type_none_allowed { - input := { "review": input_review, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 1 } test_input_volume_type_none_allowed_many_volumes { - input := { "review": input_review_many, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 2 } test_input_volume_type_allowed_all_no_volumes { - input := { "review": input_review_no_volumes, "parameters": input_parameters_wildcard} - results := violation with input as input + inp := { "review": input_review_no_volumes, "parameters": input_parameters_wildcard} + results := violation with input as inp count(results) == 0 } test_input_volume_type_none_allowed_no_volumes { - input := { "review": input_review_no_volumes, "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": input_review_no_volumes, "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } test_input_volume_type_allowed_in_list_no_volumes { - input := { "review": input_review_no_volumes, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_no_volumes, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_volume_type_allowed_in_list { - input := { "review": input_review, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_volume_type_allowed_not_in_list { - input := { "review": input_review, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 1 } test_input_volume_type_allowed_in_list_many_volumes { - input := { "review": input_review_many, "parameters": input_parameters_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_in_list} + results := violation with input as inp count(results) == 0 } test_input_volume_type_allowed_not_all_in_list_many_volumes { - input := { "review": input_review_many, "parameters": input_parameters_not_in_list} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_not_in_list} + results := violation with input as inp count(results) == 2 } test_input_volume_type_allowed_in_list_many_volumes_mixed { - input := { "review": input_review_many, "parameters": input_parameters_mixed} - results := violation with input as input + inp := { "review": input_review_many, "parameters": input_parameters_mixed} + results := violation with input as inp count(results) == 1 } test_input_volume_type_update { - input := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} - results := violation with input as input + inp := { "review": object.union(input_review, {"operation": "UPDATE"}), "parameters": input_parameters_empty} + results := violation with input as inp count(results) == 0 } diff --git a/test.sh b/test.sh index 58708c43a..e747df3f0 100755 --- a/test.sh +++ b/test.sh @@ -2,6 +2,10 @@ set -eu +# Ensure OPA strict mode compliance +# https://www.openpolicyagent.org/docs/latest/policy-language/#strict-mode +opa check --strict src + for folder in src/*/* do # TODO: enforce coverage diff --git a/website/docs/validation/allowedrepos.md b/website/docs/validation/allowedrepos.md index 9700ec895..01afadbe8 100644 --- a/website/docs/validation/allowedrepos.md +++ b/website/docs/validation/allowedrepos.md @@ -16,7 +16,7 @@ metadata: name: k8sallowedrepos annotations: metadata.gatekeeper.sh/title: "Allowed Repositories" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to begin with a string from the specified list. spec: @@ -41,22 +41,19 @@ spec: violation[{"msg": msg}] { container := input.review.object.spec.containers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] - satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)] - not any(satisfied) + not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } diff --git a/website/docs/validation/capabilities.md b/website/docs/validation/capabilities.md index 33a9430da..791a226a8 100644 --- a/website/docs/validation/capabilities.md +++ b/website/docs/validation/capabilities.md @@ -16,7 +16,7 @@ metadata: name: k8spspcapabilities annotations: metadata.gatekeeper.sh/title: "Capabilities" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a @@ -137,14 +137,11 @@ spec: count(all - dropped) > 0 } - get_default(obj, param, _default) = out { - out = obj[param] - } + get_default(obj, param, _) := obj[param] - get_default(obj, param, _default) = out { + get_default(obj, param, _default) := _default { not obj[param] not obj[param] == false - out = _default } libs: - | diff --git a/website/docs/validation/containerlimits.md b/website/docs/validation/containerlimits.md index 0b5d5306f..f000c38fd 100644 --- a/website/docs/validation/containerlimits.md +++ b/website/docs/validation/containerlimits.md @@ -17,7 +17,7 @@ metadata: name: k8scontainerlimits annotations: metadata.gatekeeper.sh/title: "Container Limits" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU limits set and constrains limits to be within the specified maximum values. @@ -78,7 +78,7 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -175,7 +175,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/website/docs/validation/containerrequests.md b/website/docs/validation/containerrequests.md index 49e4ca9f0..e1c7cbe55 100644 --- a/website/docs/validation/containerrequests.md +++ b/website/docs/validation/containerrequests.md @@ -17,7 +17,7 @@ metadata: name: k8scontainerrequests annotations: metadata.gatekeeper.sh/title: "Container Requests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires containers to have memory and CPU requests set and constrains requests to be within the specified maximum values. @@ -78,7 +78,7 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+(\\.[0-9]+)?$", orig) + regex.match("^[0-9]+(\\.[0-9]+)?$", orig) new := to_number(orig) * 1000 } @@ -175,7 +175,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/website/docs/validation/containerresourceratios.md b/website/docs/validation/containerresourceratios.md index fa20bcd8b..e2fb63447 100644 --- a/website/docs/validation/containerresourceratios.md +++ b/website/docs/validation/containerresourceratios.md @@ -17,7 +17,7 @@ metadata: name: k8scontainerratios annotations: metadata.gatekeeper.sh/title: "Container Ratios" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Sets a maximum ratio for container resource limits to requests. @@ -81,14 +81,14 @@ spec: canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+$", orig) + regex.match("^[0-9]+$", orig) new := to_number(orig) * 1000 } canonify_cpu(orig) = new { not is_number(orig) not endswith(orig, "m") - re_match("^[0-9]+[.][0-9]+$", orig) + regex.match("^[0-9]+[.][0-9]+$", orig) new := to_number(orig) * 1000 } @@ -185,7 +185,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * mem_multiple(suffix) } diff --git a/website/docs/validation/disallowedtags.md b/website/docs/validation/disallowedtags.md index dd0900c4e..656dad473 100644 --- a/website/docs/validation/disallowedtags.md +++ b/website/docs/validation/disallowedtags.md @@ -17,7 +17,7 @@ metadata: name: k8sdisallowedtags annotations: metadata.gatekeeper.sh/title: "Disallow tags" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to have an image tag different from the ones in the specified list. @@ -57,16 +57,15 @@ spec: violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tags := [forbid | tag = input.parameters.tags[_] ; forbid = endswith(container.image, concat(":", ["", tag]))] - any(tags) + tags := [tag_with_prefix | tag := input.parameters.tags[_]; tag_with_prefix := concat(":", ["", tag])] + strings.any_suffix_match(container.image, tags) msg := sprintf("container <%v> uses a disallowed tag <%v>; disallowed tags are %v", [container.name, container.image, input.parameters.tags]) } violation[{"msg": msg}] { container := input_containers[_] not is_exempt(container) - tag := [contains(container.image, ":")] - not all(tag) + not contains(container.image, ":") msg := sprintf("container <%v> didn't specify an image tag <%v>", [container.name, container.image]) } diff --git a/website/docs/validation/ephemeralstoragelimit.md b/website/docs/validation/ephemeralstoragelimit.md index c44abbbe6..954d10d52 100644 --- a/website/docs/validation/ephemeralstoragelimit.md +++ b/website/docs/validation/ephemeralstoragelimit.md @@ -17,7 +17,7 @@ metadata: name: k8scontainerephemeralstoragelimit annotations: metadata.gatekeeper.sh/title: "Container ephemeral storage limit" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires containers to have an ephemeral storage limit set and constrains the limit to be within the specified maximum values. @@ -159,7 +159,7 @@ spec: not is_number(orig) suffix := get_suffix(orig) raw := replace(orig, suffix, "") - re_match("^[0-9]+(\\.[0-9]+)?$", raw) + regex.match("^[0-9]+(\\.[0-9]+)?$", raw) new := to_number(raw) * storage_multiple(suffix) } diff --git a/website/docs/validation/forbidden-sysctls.md b/website/docs/validation/forbidden-sysctls.md index 0891bc036..91d880e3b 100644 --- a/website/docs/validation/forbidden-sysctls.md +++ b/website/docs/validation/forbidden-sysctls.md @@ -16,7 +16,7 @@ metadata: name: k8spspforbiddensysctls annotations: metadata.gatekeeper.sh/title: "Forbidden Sysctls" - metadata.gatekeeper.sh/version: 1.1.2 + metadata.gatekeeper.sh/version: 1.1.3 description: >- Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. @@ -75,7 +75,7 @@ spec: } # * may be used to forbid all sysctls - forbidden_sysctl(sysctl) { + forbidden_sysctl(_) { input.parameters.forbiddenSysctls[_] == "*" } @@ -90,7 +90,7 @@ spec: } # * may be used to allow all sysctls - allowed_sysctl(sysctl) { + allowed_sysctl(_) { input.parameters.allowedSysctls[_] == "*" } diff --git a/website/docs/validation/fsgroup.md b/website/docs/validation/fsgroup.md index cc96a5599..cb0ddcfb4 100644 --- a/website/docs/validation/fsgroup.md +++ b/website/docs/validation/fsgroup.md @@ -16,7 +16,7 @@ metadata: name: k8spspfsgroup annotations: metadata.gatekeeper.sh/title: "FS Group" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls allocating an FSGroup that owns the Pod's volumes. Corresponds to the `fsGroup` field in a PodSecurityPolicy. For more information, see @@ -70,7 +70,7 @@ spec: msg := sprintf("The provided pod spec fsGroup is not allowed, pod: %v. Allowed fsGroup: %v", [input.review.object.metadata.name, input.parameters]) } - input_fsGroup_allowed(spec) { + input_fsGroup_allowed(_) { # RunAsAny - No range is required. Allows any fsGroup ID to be specified. input.parameters.rule == "RunAsAny" } diff --git a/website/docs/validation/host-filesystem.md b/website/docs/validation/host-filesystem.md index e709f76e8..586115822 100644 --- a/website/docs/validation/host-filesystem.md +++ b/website/docs/validation/host-filesystem.md @@ -16,7 +16,7 @@ metadata: name: k8spsphostfilesystem annotations: metadata.gatekeeper.sh/title: "Host Filesystem" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of the host filesystem. Corresponds to the `allowedHostPaths` field in a PodSecurityPolicy. For more information, @@ -66,7 +66,7 @@ spec: msg := sprintf("HostPath volume %v is not allowed, pod: %v. Allowed path: %v", [volume, input.review.object.metadata.name, allowedPaths]) } - input_hostpath_violation(allowedPaths, volume) { + input_hostpath_violation(allowedPaths, _) { # An empty list means all host paths are blocked allowedPaths == [] } diff --git a/website/docs/validation/host-network-ports.md b/website/docs/validation/host-network-ports.md index 1debe644c..c322f7ab7 100644 --- a/website/docs/validation/host-network-ports.md +++ b/website/docs/validation/host-network-ports.md @@ -16,7 +16,7 @@ metadata: name: k8spsphostnetworkingports annotations: metadata.gatekeeper.sh/title: "Host Networking Ports" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and @@ -77,12 +77,12 @@ spec: o.spec.hostNetwork } - input_share_hostnetwork(o) { + input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort < input.parameters.min } - input_share_hostnetwork(o) { + input_share_hostnetwork(_) { hostPort := input_containers[_].ports[_].hostPort hostPort > input.parameters.max } diff --git a/website/docs/validation/httpsonly.md b/website/docs/validation/httpsonly.md index 5d0775e1f..417dd9f12 100644 --- a/website/docs/validation/httpsonly.md +++ b/website/docs/validation/httpsonly.md @@ -17,7 +17,7 @@ metadata: name: k8shttpsonly annotations: metadata.gatekeeper.sh/title: "HTTPS Only" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires Ingress resources to be HTTPS only. Ingress resources must include the `kubernetes.io/ingress.allow-http` annotation, set to `false`. @@ -52,19 +52,19 @@ spec: violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not https_complete(ingress) - not tls_is_optional(ingress) + not tls_is_optional msg := sprintf("Ingress should be https. tls configuration and allow-http=false annotation are required for %v", [ingress.metadata.name]) } violation[{"msg": msg}] { input.review.object.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) + regex.match("^(extensions|networking.k8s.io)/", input.review.object.apiVersion) ingress := input.review.object not annotation_complete(ingress) - not tls_not_optional(ingress) + tls_is_optional msg := sprintf("Ingress should be https. The allow-http=false annotation is required for %v", [ingress.metadata.name]) } @@ -78,17 +78,9 @@ spec: ingress.metadata.annotations["kubernetes.io/ingress.allow-http"] == "false" } - tls_is_optional(ingress) = true { + tls_is_optional { parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - is_boolean(tlsOptional) - true == tlsOptional - } - - tls_not_optional(ingress) = true { - parameters := object.get(input, "parameters", {}) - tlsOptional := object.get(parameters, "tlsOptional", false) - true != tlsOptional + object.get(parameters, "tlsOptional", false) == true } ``` diff --git a/website/docs/validation/imagedigests.md b/website/docs/validation/imagedigests.md index f50884cba..6519bb5cc 100644 --- a/website/docs/validation/imagedigests.md +++ b/website/docs/validation/imagedigests.md @@ -17,7 +17,7 @@ metadata: name: k8simagedigests annotations: metadata.gatekeeper.sh/title: "Image Digests" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to contain a digest. @@ -55,24 +55,21 @@ spec: violation[{"msg": msg}] { container := input.review.object.spec.containers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] not is_exempt(container) - satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)] - not all(satisfied) + not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image) msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image]) } libs: diff --git a/website/docs/validation/noupdateserviceaccount.md b/website/docs/validation/noupdateserviceaccount.md index 825bfcfe4..bacb4a075 100644 --- a/website/docs/validation/noupdateserviceaccount.md +++ b/website/docs/validation/noupdateserviceaccount.md @@ -16,7 +16,7 @@ metadata: name: noupdateserviceaccount annotations: metadata.gatekeeper.sh/title: "Block updating Service Account" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: "Blocks updating the service account on resources that abstract over Pods. This policy is ignored in audit mode." spec: crd: @@ -42,13 +42,15 @@ spec: rego: | package noupdateserviceaccount - privileged(userInfo, allowedUsers, allowedGroups) { + privileged(userInfo, allowedUsers, _) { # Allow if the user is in allowedUsers. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. username := object.get(userInfo, "username", "") allowedUsers[_] == username - } { + } + + privileged(userInfo, _, allowedGroups) { # Allow if the user's groups intersect allowedGroups. # Use object.get so omitted parameters can't cause policy bypass by # evaluating to undefined. diff --git a/website/docs/validation/proc-mount.md b/website/docs/validation/proc-mount.md index 2fd4cf590..9eb1dd666 100644 --- a/website/docs/validation/proc-mount.md +++ b/website/docs/validation/proc-mount.md @@ -16,7 +16,7 @@ metadata: name: k8spspprocmount annotations: metadata.gatekeeper.sh/title: "Proc Mount" - metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/version: 1.0.3 description: >- Controls the allowed `procMount` types for the container. Corresponds to the `allowedProcMountTypes` field in a PodSecurityPolicy. For more @@ -80,7 +80,7 @@ spec: allowedProcMount == "default" lower(c.securityContext.procMount) == "default" } - input_proc_mount_type_allowed(allowedProcMount, c) { + input_proc_mount_type_allowed(allowedProcMount, _) { allowedProcMount == "unmasked" } diff --git a/website/docs/validation/replicalimits.md b/website/docs/validation/replicalimits.md index 74e16a4dd..d2da9c9e0 100644 --- a/website/docs/validation/replicalimits.md +++ b/website/docs/validation/replicalimits.md @@ -16,7 +16,7 @@ metadata: name: k8sreplicalimits annotations: metadata.gatekeeper.sh/title: "Replica Limits" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Requires that objects with the field `spec.replicas` (Deployments, ReplicaSets, etc.) specify a number of replicas within defined ranges. @@ -58,7 +58,7 @@ spec: } input_replica_limit(spec) { - provided := input.review.object.spec.replicas + provided := spec.replicas count(input.parameters.ranges) > 0 range := input.parameters.ranges[_] value_within_range(range, provided) diff --git a/website/docs/validation/requiredannotations.md b/website/docs/validation/requiredannotations.md index 13480fc9f..0dafa7901 100644 --- a/website/docs/validation/requiredannotations.md +++ b/website/docs/validation/requiredannotations.md @@ -16,7 +16,7 @@ metadata: name: k8srequiredannotations annotations: metadata.gatekeeper.sh/title: "Required Annotations" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified annotations, with values matching provided regular expressions. @@ -66,7 +66,7 @@ spec: expected := input.parameters.annotations[_] expected.key == key expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) msg := sprintf("Annotation <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) } diff --git a/website/docs/validation/requiredlabels.md b/website/docs/validation/requiredlabels.md index 7086a6d51..e4bcc63ad 100644 --- a/website/docs/validation/requiredlabels.md +++ b/website/docs/validation/requiredlabels.md @@ -16,7 +16,7 @@ metadata: name: k8srequiredlabels annotations: metadata.gatekeeper.sh/title: "Required Labels" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires resources to contain specified labels, with values matching provided regular expressions. @@ -53,14 +53,11 @@ spec: rego: | package k8srequiredlabels - get_message(parameters, _default) = msg { + get_message(parameters, _default) := _default { not parameters.message - msg := _default } - get_message(parameters, _default) = msg { - msg := parameters.message - } + get_message(parameters, _) := parameters.message violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} @@ -77,7 +74,7 @@ spec: expected.key == key # do not match if allowedRegex is not defined, or is an empty string expected.allowedRegex != "" - not re_match(expected.allowedRegex, value) + not regex.match(expected.allowedRegex, value) def_msg := sprintf("Label <%v: %v> does not satisfy allowed regex: %v", [key, value, expected.allowedRegex]) msg := get_message(input.parameters, def_msg) } diff --git a/website/docs/validation/seccomp.md b/website/docs/validation/seccomp.md index 7fbe4fb59..b9b28087c 100644 --- a/website/docs/validation/seccomp.md +++ b/website/docs/validation/seccomp.md @@ -16,7 +16,7 @@ metadata: name: k8spspseccomp annotations: metadata.gatekeeper.sh/title: "Seccomp" - metadata.gatekeeper.sh/version: 1.0.0 + metadata.gatekeeper.sh/version: 1.0.1 description: >- Controls the seccomp profile used by containers. Corresponds to the `seccomp.security.alpha.kubernetes.io/allowedProfileNames` annotation on @@ -110,7 +110,7 @@ spec: msg := get_message(result.profile, result.file, name, result.location, allowed_profiles) } - get_message(profile, file, name, location, allowed_profiles) = message { + get_message(profile, _, name, location, allowed_profiles) = message { not profile == "Localhost" message := sprintf("Seccomp profile '%v' is not allowed for container '%v'. Found at: %v. Allowed profiles: %v", [profile, name, location, allowed_profiles]) } @@ -133,7 +133,7 @@ spec: } # Simple allowed Profiles - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { not startswith(lower(profile), "localhost") profile == allowed[_] } @@ -148,20 +148,20 @@ spec: } # seccomp Localhost with wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { profile == "Localhost" input_wildcard_allowed_files profile == allowed[_] } # annotation localhost with wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { "localhost/*" == allowed[_] startswith(profile, "localhost/") } # annotation localhost without wildcard - allowed_profile(profile, file, allowed) { + allowed_profile(profile, _, allowed) { startswith(profile, "localhost/") profile == allowed[_] } diff --git a/website/docs/validation/selinux.md b/website/docs/validation/selinux.md index 3c33766b5..397718e43 100644 --- a/website/docs/validation/selinux.md +++ b/website/docs/validation/selinux.md @@ -16,7 +16,7 @@ metadata: name: k8spspselinuxv2 annotations: metadata.gatekeeper.sh/title: "SELinux V2" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Defines an allow-list of seLinuxOptions configurations for pod containers. Corresponds to a PodSecurityPolicy requiring SELinux configs. @@ -106,7 +106,7 @@ spec: field_allowed(field, options, params) { params[field] == options[field] } - field_allowed(field, options, params) { + field_allowed(field, options, _) { not has_field(options, field) } diff --git a/website/docs/validation/uniqueingresshost.md b/website/docs/validation/uniqueingresshost.md index d8b14494c..dc57f4853 100644 --- a/website/docs/validation/uniqueingresshost.md +++ b/website/docs/validation/uniqueingresshost.md @@ -17,7 +17,7 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/version: 1.0.4 metadata.gatekeeper.sh/requires-sync-data: | "[ [ @@ -55,10 +55,10 @@ spec: violation[{"msg": msg}] { input.review.kind.kind == "Ingress" - re_match("^(extensions|networking.k8s.io)$", input.review.kind.group) + regex.match("^(extensions|networking.k8s.io)$", input.review.kind.group) host := input.review.object.spec.rules[_].host other := data.inventory.namespace[_][otherapiversion]["Ingress"][name] - re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion) + regex.match("^(extensions|networking.k8s.io)/.+$", otherapiversion) other.spec.rules[_].host == host not identical(other, input.review) msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host]) diff --git a/website/docs/validation/users.md b/website/docs/validation/users.md index 0b1ddfb77..1529b79bc 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.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Controls the user and group IDs of the container and some volumes. Corresponds to the `runAsUser`, `runAsGroup`, `supplementalGroups`, and @@ -194,11 +194,11 @@ spec: msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name]) } - accept_users("RunAsAny", provided_user) {true} + accept_users("RunAsAny", _) - accept_users("MustRunAsNonRoot", provided_user) = res {res := provided_user != 0} + accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0 - accept_users("MustRunAs", provided_user) = res { + accept_users("MustRunAs", provided_user) := res { ranges := input.parameters.runAsUser.ranges res := is_in_range(provided_user, ranges) } @@ -227,18 +227,15 @@ spec: msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params]) } - accept_value("RunAsAny", provided_value, ranges) {true} + accept_value("RunAsAny", _, _) - accept_value("MayRunAs", provided_value, ranges) = res { res := is_in_range(provided_value, ranges)} + accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges) - accept_value("MustRunAs", provided_value, ranges) = res { res := 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, review) = out { - container_value := get_seccontext_field(field, container) - out := container_value - } + 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 { diff --git a/website/docs/validation/volumes.md b/website/docs/validation/volumes.md index f2b8042bd..7b032e9da 100644 --- a/website/docs/validation/volumes.md +++ b/website/docs/validation/volumes.md @@ -16,7 +16,7 @@ metadata: name: k8spspvolumetypes annotations: metadata.gatekeeper.sh/title: "Volume Types" - metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/version: 1.0.2 description: >- Restricts mountable volume types to those specified by the user. Corresponds to the `volumes` field in a PodSecurityPolicy. For more @@ -60,7 +60,7 @@ spec: } # * may be used to allow all volume types - input_volume_type_allowed(field) { + input_volume_type_allowed(_) { input.parameters.volumes[_] == "*" }