From 5bfc1aa25b619655cc05d82fcd98a5992ef8eb4a Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Mon, 15 Jul 2024 15:36:45 +0530 Subject: [PATCH] feat: add miscellaneous policies in CEL expressions - Part 3 (#1028) * copy prevent-linkerd-pod-injection-override Signed-off-by: Chandan-DK * add kyverno tests for prevent-linkerd-pod-injection-override Signed-off-by: Chandan-DK * convert prevent-linkerd-pod-injection-override Signed-off-by: Chandan-DK * add metadata section to template This is done in order to avoid no such key: metadata error in the kyverno tests for the cel policy Signed-off-by: Chandan-DK * add kyverno tests for prevent-linkerd-pod-injection-override in regular policy Signed-off-by: Chandan-DK * copy prevent-linkerd-port-skipping Signed-off-by: Chandan-DK * correct invalid chainsaw test resources to remove errors Signed-off-by: Chandan-DK * add kyverno tests Signed-off-by: Chandan-DK * convert prevent-linkerd-port-skipping Signed-off-by: Chandan-DK * copy require-linkerd-mesh-injection Signed-off-by: Chandan-DK * add kyverno tests for require-linkerd-mesh-injection Signed-off-by: Chandan-DK * convert require-linkerd-mesh-injection Signed-off-by: Chandan-DK * copy disallow-ingress-nginx-custom-snippets Signed-off-by: Chandan-DK * convert disallow-ingress-nginx-custom-snippets Signed-off-by: Chandan-DK * copy restrict-annotations Signed-off-by: Chandan-DK * convert restrict-annotations Signed-off-by: Chandan-DK * copy restrict-ingress-paths Signed-off-by: Chandan-DK * add kyverno test for one more failing condition Signed-off-by: Chandan-DK * convert restrict-ingress-paths Signed-off-by: Chandan-DK * copy check-routes Signed-off-by: Chandan-DK * convert check-routes Signed-off-by: Chandan-DK * copy disallow-deprecated-apis/ Signed-off-by: Chandan-DK * convert disallow-deprecated-apis Signed-off-by: Chandan-DK * copy disallow-default-tlsoptions Signed-off-by: Chandan-DK * convert disallow-default-tlsoptions Signed-off-by: Chandan-DK * copy add-psa-namespace-reporting Signed-off-by: Chandan-DK * convert add-psa-namespace-reporting Signed-off-by: Chandan-DK * copy deny-privileged-profile Signed-off-by: Chandan-DK * convert deny-privileged-profile Signed-off-by: Chandan-DK * add kyverno tests for deny-privileged-profile Signed-off-by: Chandan-DK * copy disallow-jenkins-pipeline-strategy Signed-off-by: Chandan-DK * convert disallow-jenkins-pipeline-strategy Signed-off-by: Chandan-DK * copy disallow-security-context-constraint-anyuid Signed-off-by: Chandan-DK * convert disallow-security-context-constraint-anyuid Signed-off-by: Chandan-DK * copy openshift-cel/disallow-self-provisioner-binding Signed-off-by: Chandan-DK * convert disallow-self-provisioner-binding Signed-off-by: Chandan-DK * copy enforce-etcd-encryption Signed-off-by: Chandan-DK * convert enforce-etcd-encryption Signed-off-by: Chandan-DK * add CI tests for cel policies Signed-off-by: Chandan-DK * remove comments for CI tests Signed-off-by: Chandan-DK * rename files for clarity Signed-off-by: Chandan-DK * specify CREATE and UPDATE operations explicitly Signed-off-by: Chandan-DK * remove disallow-self-provisioner-binding as it gives errors that needs further investigation Signed-off-by: Chandan-DK --------- Signed-off-by: Chandan-DK Co-authored-by: Mariam Fahmy --- .github/workflows/test.yml | 11 +- .../.chainsaw-test/bad-pod.yaml | 10 + .../.chainsaw-test/bad-podcontrollers.yaml | 42 ++++ .../.chainsaw-test/chainsaw-test.yaml | 38 ++++ .../.chainsaw-test/good-pod.yaml | 20 ++ .../.chainsaw-test/good-podcontrollers.yaml | 83 ++++++++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 51 +++++ .../artifacthub-pkg.yml | 23 +++ ...revent-linkerd-pod-injection-override.yaml | 35 ++++ .../.chainsaw-test/bad-pod.yaml | 36 ++++ .../.chainsaw-test/bad-podcontrollers.yaml | 136 +++++++++++++ .../.chainsaw-test/chainsaw-test.yaml | 38 ++++ .../.chainsaw-test/good-pod.yaml | 20 ++ .../.chainsaw-test/good-podcontrollers.yaml | 83 ++++++++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 58 ++++++ .../artifacthub-pkg.yml | 23 +++ .../prevent-linkerd-port-skipping.yaml | 37 ++++ .../.chainsaw-test/bad-ns.yaml | 19 ++ .../.chainsaw-test/chainsaw-test.yaml | 31 +++ .../.chainsaw-test/good-ns.yaml | 15 ++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 26 +++ .../artifacthub-pkg.yml | 23 +++ .../require-linkerd-mesh-injection.yaml | 34 ++++ .../.chainsaw-test/good-podcontrollers.yaml | 3 + .../.kyverno-test/kyverno-test.yaml | 51 +++++ .../.chainsaw-test/bad-pod.yaml | 8 +- .../.chainsaw-test/bad-podcontrollers.yaml | 16 +- .../.chainsaw-test/good-podcontrollers.yaml | 3 + .../.kyverno-test/kyverno-test.yaml | 58 ++++++ .../.kyverno-test/kyverno-test.yaml | 26 +++ .../.chainsaw-test/chainsaw-test.yaml | 30 +++ .../.chainsaw-test/cm-bad.yaml | 6 + .../.chainsaw-test/cm-good.yaml | 18 ++ .../.chainsaw-test/ig-bad.yaml | 63 ++++++ .../.chainsaw-test/ig-good.yaml | 50 +++++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 35 ++++ .../.kyverno-test/resources.yaml | 81 ++++++++ .../artifacthub-pkg.yml | 24 +++ ...isallow-ingress-nginx-custom-snippets.yaml | 49 +++++ .../.chainsaw-test/chainsaw-test.yaml | 23 +++ .../.chainsaw-test/ig-bad.yaml | 129 +++++++++++++ .../.chainsaw-test/ig-good.yaml | 49 +++++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 26 +++ .../.kyverno-test/resources.yaml | 180 ++++++++++++++++++ .../restrict-annotations/artifacthub-pkg.yml | 24 +++ .../restrict-annotations.yaml | 44 +++++ .../.chainsaw-test/chainsaw-test.yaml | 23 +++ .../.chainsaw-test/ig-bad.yaml | 85 +++++++++ .../.chainsaw-test/ig-good.yaml | 23 +++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 25 +++ .../.kyverno-test/resources.yaml | 109 +++++++++++ .../artifacthub-pkg.yml | 24 +++ .../restrict-ingress-paths.yaml | 40 ++++ .../.chainsaw-test/ig-bad.yaml | 19 +- .../.kyverno-test/kyverno-test.yaml | 1 + .../.kyverno-test/resources.yaml | 19 +- .../.chainsaw-test/chainsaw-test.yaml | 23 +++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.chainsaw-test/route-bad.yaml | 12 ++ .../.chainsaw-test/route-good.yaml | 66 +++++++ .../.kyverno-test/kyverno-test.yaml | 23 +++ .../check-routes/.kyverno-test/resources.yaml | 78 ++++++++ .../check-routes/artifacthub-pkg.yml | 23 +++ openshift-cel/check-routes/check-routes.yaml | 34 ++++ .../.kyverno-test/kyverno-test.yaml | 33 ++++ .../.kyverno-test/resources.yaml | 89 +++++++++ .../artifacthub-pkg.yml | 23 +++ .../disallow-deprecated-apis.yaml | 41 ++++ .../.kyverno-test/kyverno-test.yaml | 23 +++ .../.kyverno-test/resources.yaml | 43 +++++ .../artifacthub-pkg.yml | 23 +++ .../disallow-jenkins-pipeline-strategy.yaml | 35 ++++ .../.chainsaw-test/chainsaw-test.yaml | 44 +++++ .../.chainsaw-test/clusterroles-bad.yaml | 34 ++++ .../.chainsaw-test/clusterroles-good.yaml | 8 + .../.chainsaw-test/crb-bad.yaml | 12 ++ .../.chainsaw-test/crb-good.yaml | 12 ++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.chainsaw-test/rb-bad.yaml | 12 ++ .../.chainsaw-test/rb-good.yaml | 12 ++ .../.chainsaw-test/roles-bad.yaml | 35 ++++ .../.chainsaw-test/roles-good.yaml | 8 + .../.kyverno-test/kyverno-test.yaml | 59 ++++++ .../.kyverno-test/resources.yaml | 154 +++++++++++++++ .../artifacthub-pkg.yml | 23 +++ ...ow-security-context-constraint-anyuid.yaml | 51 +++++ .../.kyverno-test/kyverno-test.yaml | 21 ++ .../.kyverno-test/resources.yaml | 16 ++ .../artifacthub-pkg.yml | 23 +++ .../enforce-etcd-encryption.yaml | 34 ++++ .../.chainsaw-test/chainsaw-test.yaml | 31 +++ .../namespace-with-psa-labels.yaml | 6 + .../namespace-without-psa-labels.yaml | 4 + .../.chainsaw-test/policy-ready.yaml | 9 + .../.kyverno-test/kyverno-test.yaml | 22 +++ .../namespace-with-psa-labels.yaml | 6 + .../namespace-without-psa-labels.yaml | 4 + .../add-psa-namespace-reporting.yaml | 42 ++++ .../artifacthub-pkg.yml | 24 +++ .../.chainsaw-test/chainsaw-test.yaml | 98 ++++++++++ .../.chainsaw-test/cr.yaml | 11 ++ .../.chainsaw-test/crb.yaml | 12 ++ .../.chainsaw-test/ns-bad.yaml | 14 ++ .../.chainsaw-test/ns-good.yaml | 18 ++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.kyverno-test/kyverno-test.yaml | 16 ++ .../artifacthub-pkg.yml | 23 +++ .../deny-privileged-profile.yaml | 44 +++++ .../.kyverno-test/kyverno-test.yaml | 16 ++ .../.chainsaw-test/chainsaw-test.yaml | 87 +++++++++ .../.chainsaw-test/cr.yaml | 11 ++ .../.chainsaw-test/crb.yaml | 12 ++ .../.chainsaw-test/crd-assert.yaml | 12 ++ .../.chainsaw-test/policy-ready.yaml | 6 + .../.chainsaw-test/tlsoption.yaml | 21 ++ .../.kyverno-test/kyverno-test.yaml | 15 ++ .../.kyverno-test/resource.yaml | 22 +++ .../artifacthub-pkg.yml | 23 +++ .../disallow-default-tlsoptions.yaml | 37 ++++ 125 files changed, 4066 insertions(+), 17 deletions(-) create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-pod.yaml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-podcontrollers.yaml create mode 100755 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/chainsaw-test.yaml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-pod.yaml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml create mode 100755 linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/policy-ready.yaml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/artifacthub-pkg.yml create mode 100644 linkerd-cel/prevent-linkerd-pod-injection-override/prevent-linkerd-pod-injection-override.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml create mode 100755 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/chainsaw-test.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-pod.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml create mode 100755 linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/policy-ready.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/artifacthub-pkg.yml create mode 100644 linkerd-cel/prevent-linkerd-port-skipping/prevent-linkerd-port-skipping.yaml create mode 100644 linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/bad-ns.yaml create mode 100755 linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/chainsaw-test.yaml create mode 100644 linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/good-ns.yaml create mode 100755 linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/policy-ready.yaml create mode 100644 linkerd-cel/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml create mode 100644 linkerd-cel/require-linkerd-mesh-injection/artifacthub-pkg.yml create mode 100644 linkerd-cel/require-linkerd-mesh-injection/require-linkerd-mesh-injection.yaml create mode 100644 linkerd/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml create mode 100644 linkerd/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml create mode 100644 linkerd/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml create mode 100755 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/chainsaw-test.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-bad.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-good.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-bad.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-good.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/policy-ready.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/kyverno-test.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/resources.yaml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/artifacthub-pkg.yml create mode 100644 nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml create mode 100755 nginx-ingress-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-bad.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-good.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/.kyverno-test/resources.yaml create mode 100644 nginx-ingress-cel/restrict-annotations/artifacthub-pkg.yml create mode 100644 nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml create mode 100755 nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/chainsaw-test.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-good.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/policy-ready.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/resources.yaml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/artifacthub-pkg.yml create mode 100644 nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml create mode 100755 openshift-cel/check-routes/.chainsaw-test/chainsaw-test.yaml create mode 100644 openshift-cel/check-routes/.chainsaw-test/policy-ready.yaml create mode 100644 openshift-cel/check-routes/.chainsaw-test/route-bad.yaml create mode 100644 openshift-cel/check-routes/.chainsaw-test/route-good.yaml create mode 100644 openshift-cel/check-routes/.kyverno-test/kyverno-test.yaml create mode 100644 openshift-cel/check-routes/.kyverno-test/resources.yaml create mode 100644 openshift-cel/check-routes/artifacthub-pkg.yml create mode 100644 openshift-cel/check-routes/check-routes.yaml create mode 100644 openshift-cel/disallow-deprecated-apis/.kyverno-test/kyverno-test.yaml create mode 100644 openshift-cel/disallow-deprecated-apis/.kyverno-test/resources.yaml create mode 100644 openshift-cel/disallow-deprecated-apis/artifacthub-pkg.yml create mode 100644 openshift-cel/disallow-deprecated-apis/disallow-deprecated-apis.yaml create mode 100644 openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/kyverno-test.yaml create mode 100644 openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/resources.yaml create mode 100644 openshift-cel/disallow-jenkins-pipeline-strategy/artifacthub-pkg.yml create mode 100644 openshift-cel/disallow-jenkins-pipeline-strategy/disallow-jenkins-pipeline-strategy.yaml create mode 100755 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/chainsaw-test.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-bad.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-good.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-bad.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-good.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/policy-ready.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-bad.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-good.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-bad.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-good.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/kyverno-test.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/resources.yaml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/artifacthub-pkg.yml create mode 100644 openshift-cel/disallow-security-context-constraint-anyuid/disallow-security-context-constraint-anyuid.yaml create mode 100644 openshift-cel/enforce-etcd-encryption/.kyverno-test/kyverno-test.yaml create mode 100644 openshift-cel/enforce-etcd-encryption/.kyverno-test/resources.yaml create mode 100644 openshift-cel/enforce-etcd-encryption/artifacthub-pkg.yml create mode 100644 openshift-cel/enforce-etcd-encryption/enforce-etcd-encryption.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.chainsaw-test/chainsaw-test.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-with-psa-labels.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-without-psa-labels.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.chainsaw-test/policy-ready.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.kyverno-test/kyverno-test.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-with-psa-labels.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-without-psa-labels.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/add-psa-namespace-reporting.yaml create mode 100644 psa-cel/add-psa-namespace-reporting/artifacthub-pkg.yml create mode 100755 psa-cel/deny-privileged-profile/.chainsaw-test/chainsaw-test.yaml create mode 100755 psa-cel/deny-privileged-profile/.chainsaw-test/cr.yaml create mode 100755 psa-cel/deny-privileged-profile/.chainsaw-test/crb.yaml create mode 100644 psa-cel/deny-privileged-profile/.chainsaw-test/ns-bad.yaml create mode 100644 psa-cel/deny-privileged-profile/.chainsaw-test/ns-good.yaml create mode 100755 psa-cel/deny-privileged-profile/.chainsaw-test/policy-ready.yaml create mode 100644 psa-cel/deny-privileged-profile/.kyverno-test/kyverno-test.yaml create mode 100644 psa-cel/deny-privileged-profile/artifacthub-pkg.yml create mode 100644 psa-cel/deny-privileged-profile/deny-privileged-profile.yaml create mode 100644 psa/deny-privileged-profile/.kyverno-test/kyverno-test.yaml create mode 100755 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/chainsaw-test.yaml create mode 100755 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/cr.yaml create mode 100755 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crb.yaml create mode 100755 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crd-assert.yaml create mode 100755 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/policy-ready.yaml create mode 100644 traefik-cel/disallow-default-tlsoptions/.chainsaw-test/tlsoption.yaml create mode 100644 traefik-cel/disallow-default-tlsoptions/.kyverno-test/kyverno-test.yaml create mode 100644 traefik-cel/disallow-default-tlsoptions/.kyverno-test/resource.yaml create mode 100644 traefik-cel/disallow-default-tlsoptions/artifacthub-pkg.yml create mode 100644 traefik-cel/disallow-default-tlsoptions/disallow-default-tlsoptions.yaml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6de6c7276..73f7d2e0a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,8 +53,11 @@ jobs: - ^kubeops$ - ^kubevirt$ - ^linkerd$ + - ^linkerd-cel$ - ^nginx-ingress$ + - ^nginx-ingress-cel$ - ^openshift$ + - ^openshift-cel$ - ^other$/^a - ^other-cel$/^a - ^other$/^[b-d] @@ -72,10 +75,12 @@ jobs: - ^pod-security$ - ^pod-security-cel$ - ^psa$ + - ^psa-cel$ - ^psp-migration$ - # - ^tekton - # - ^traefik - # - ^velero + - ^tekton$ + - ^traefik$ + - ^traefik-cel$ + - ^velero$ runs-on: ubuntu-latest name: ${{ matrix.k8s-version.name }} - ${{ matrix.tests }} steps: diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-pod.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-pod.yaml new file mode 100644 index 000000000..2ffa3ce71 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + linkerd.io/inject: disabled + name: badpod01 +spec: + containers: + - image: busybox:1.35 + name: busybox \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-podcontrollers.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-podcontrollers.yaml new file mode 100644 index 000000000..0ef55981b --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/bad-podcontrollers.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + linkerd.io/inject: disabled + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + linkerd.io/inject: disabled + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/chainsaw-test.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..9051a94fb --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: prevent-linkerd-pod-injection-override +spec: + steps: + - name: step-01 + try: + - apply: + file: ../prevent-linkerd-pod-injection-override.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: prevent-linkerd-pod-injection-override + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: good-pod.yaml + - apply: + file: good-podcontrollers.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-pod.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-podcontrollers.yaml diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-pod.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-pod.yaml new file mode 100644 index 000000000..826bd837a --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-pod.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + linkerd.io/inject: enabled + name: goodpod01 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: goodpod02 +spec: + containers: + - image: busybox:1.35 + name: busybox + resources: {} \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml new file mode 100644 index 000000000..876c42be2 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + linkerd.io/inject: enabled + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + linkerd.io/inject: enabled + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/policy-ready.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..2d21edf25 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-linkerd-pod-injection-override +status: + ready: true diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..123a46aa0 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,51 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-linkerd-pod-injection-override +policies: +- ../prevent-linkerd-pod-injection-override.yaml +resources: +- ../.chainsaw-test/bad-pod.yaml +- ../.chainsaw-test/bad-podcontrollers.yaml +- ../.chainsaw-test/good-pod.yaml +- ../.chainsaw-test/good-podcontrollers.yaml +results: +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Pod + resources: + - badpod01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Deployment + resources: + - baddeploy01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: CronJob + resources: + - badcronjob01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/artifacthub-pkg.yml b/linkerd-cel/prevent-linkerd-pod-injection-override/artifacthub-pkg.yml new file mode 100644 index 000000000..41668ea02 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: prevent-linkerd-pod-injection-override-cel +version: 1.0.0 +displayName: Prevent Linkerd Pod Injection Override in CEL expressions +description: >- + Setting the annotation on a Pod (or its controller) `linkerd.io/inject` to `disabled` may effectively disable mesh participation for that workload reducing security and visibility. This policy prevents setting the annotation `linkerd.io/inject` to `disabled` for Pods. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/linkerd-cel/prevent-linkerd-pod-injection-override/prevent-linkerd-pod-injection-override.yaml + ``` +keywords: + - kyverno + - Linkerd + - CEL Expressions +readme: | + Setting the annotation on a Pod (or its controller) `linkerd.io/inject` to `disabled` may effectively disable mesh participation for that workload reducing security and visibility. This policy prevents setting the annotation `linkerd.io/inject` to `disabled` for Pods. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Linkerd in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod" +digest: 795a7d5ae06f9720bdbcc00ced965d1f7a28540c965628a47abc5621fb8d0033 +createdAt: "2024-05-21T15:39:18Z" diff --git a/linkerd-cel/prevent-linkerd-pod-injection-override/prevent-linkerd-pod-injection-override.yaml b/linkerd-cel/prevent-linkerd-pod-injection-override/prevent-linkerd-pod-injection-override.yaml new file mode 100644 index 000000000..cbed7f953 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-pod-injection-override/prevent-linkerd-pod-injection-override.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-linkerd-pod-injection-override + annotations: + policies.kyverno.io/title: Prevent Linkerd Pod Injection Override in CEL expressions + policies.kyverno.io/category: Linkerd in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Setting the annotation on a Pod (or its controller) `linkerd.io/inject` to + `disabled` may effectively disable mesh participation for that workload reducing + security and visibility. This policy prevents setting the annotation `linkerd.io/inject` + to `disabled` for Pods. +spec: + validationFailureAction: Audit + background: true + rules: + - name: pod-injection-override + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "!has(object.metadata.annotations) || !('linkerd.io/inject' in object.metadata.annotations) || object.metadata.annotations['linkerd.io/inject'] != 'disabled'" + message: "Pods may not disable sidecar injection." + diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml new file mode 100644 index 000000000..1d3b1cbc3 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + foo: bar + config.linkerd.io/skip-inbound-ports: "true" + name: badpod01 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + config.linkerd.io/skip-outbound-ports: "true" + foo: bar + name: badpod02 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + foo: bar + config.linkerd.io/skip-outbound-ports: "true" + config.linkerd.io/skip-inbound-ports: "true" + name: badpod03 +spec: + containers: + - image: busybox:1.35 + name: busybox \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml new file mode 100644 index 000000000..3d4093257 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml @@ -0,0 +1,136 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + foo: bar + config.linkerd.io/skip-inbound-ports: "true" + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + config.linkerd.io/skip-outbound-ports: "true" + foo: bar + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy03 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + foo: bar + config.linkerd.io/skip-inbound-ports: "true" + config.linkerd.io/skip-outbound-ports: "true" + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + config.linkerd.io/skip-outbound-ports: "true" + foo: bar + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + foo: bar + config.linkerd.io/skip-inbound-ports: "true" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob03 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + foo: bar + config.linkerd.io/skip-outbound-ports: "true" + config.linkerd.io/skip-inbound-ports: "true" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/chainsaw-test.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..c85c17614 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: prevent-linkerd-port-skipping +spec: + steps: + - name: step-01 + try: + - apply: + file: ../prevent-linkerd-port-skipping.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: prevent-linkerd-port-skipping + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: good-pod.yaml + - apply: + file: good-podcontrollers.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-pod.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-podcontrollers.yaml diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-pod.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-pod.yaml new file mode 100644 index 000000000..feddec893 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-pod.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goodpod01 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + foo: bar + name: goodpod02 +spec: + containers: + - image: busybox:1.35 + name: busybox + resources: {} \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml new file mode 100644 index 000000000..e8c4c6706 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + annotations: + foo: bar + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + foo: bar + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/policy-ready.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..538df5440 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-linkerd-port-skipping +status: + ready: true diff --git a/linkerd-cel/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml b/linkerd-cel/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..3eef768b6 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,58 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-linkerd-port-skipping +policies: +- ../prevent-linkerd-port-skipping.yaml +resources: +- ../.chainsaw-test/bad-pod.yaml +- ../.chainsaw-test/bad-podcontrollers.yaml +- ../.chainsaw-test/good-pod.yaml +- ../.chainsaw-test/good-podcontrollers.yaml +results: +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Pod + resources: + - badpod01 + - badpod02 + - badpod03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Deployment + resources: + - baddeploy01 + - baddeploy02 + - baddeploy03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: CronJob + resources: + - badcronjob01 + - badcronjob02 + - badcronjob03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass + diff --git a/linkerd-cel/prevent-linkerd-port-skipping/artifacthub-pkg.yml b/linkerd-cel/prevent-linkerd-port-skipping/artifacthub-pkg.yml new file mode 100644 index 000000000..4ab092a6c --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: prevent-linkerd-port-skipping-cel +version: 1.0.0 +displayName: Prevent Linkerd Port Skipping in CEL expressions +description: >- + Linkerd has the ability to skip inbound and outbound ports assigned to Pods, exempting them from mTLS. This can be important in some narrow use cases but generally should be avoided. This policy prevents Pods from setting the annotations `config.linkerd.io/skip-inbound-ports` or `config.linkerd.io/skip-outbound-ports`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/linkerd-cel/prevent-linkerd-port-skipping/prevent-linkerd-port-skipping.yaml + ``` +keywords: + - kyverno + - Linkerd + - CEL Expressions +readme: | + Linkerd has the ability to skip inbound and outbound ports assigned to Pods, exempting them from mTLS. This can be important in some narrow use cases but generally should be avoided. This policy prevents Pods from setting the annotations `config.linkerd.io/skip-inbound-ports` or `config.linkerd.io/skip-outbound-ports`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Linkerd in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod" +digest: bb047cee4e04c6939ccbdafe386dc0a84ea7e7242fe476a67ab6daf93dbec98f +createdAt: "2024-05-21T15:57:57Z" diff --git a/linkerd-cel/prevent-linkerd-port-skipping/prevent-linkerd-port-skipping.yaml b/linkerd-cel/prevent-linkerd-port-skipping/prevent-linkerd-port-skipping.yaml new file mode 100644 index 000000000..d95aca938 --- /dev/null +++ b/linkerd-cel/prevent-linkerd-port-skipping/prevent-linkerd-port-skipping.yaml @@ -0,0 +1,37 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-linkerd-port-skipping + annotations: + policies.kyverno.io/title: Prevent Linkerd Port Skipping in CEL expressions + policies.kyverno.io/category: Linkerd in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Linkerd has the ability to skip inbound and outbound ports assigned to Pods, exempting + them from mTLS. This can be important in some narrow use cases but + generally should be avoided. This policy prevents Pods from setting + the annotations `config.linkerd.io/skip-inbound-ports` or `config.linkerd.io/skip-outbound-ports`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: pod-prevent-port-skipping + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + !has(object.metadata.annotations) || + (!('config.linkerd.io/skip-inbound-ports' in object.metadata.annotations) && !('config.linkerd.io/skip-outbound-ports' in object.metadata.annotations)) + message: "Pods may not skip ports. The annotations `config.linkerd.io/skip-inbound-ports` or `config.linkerd.io/skip-outbound-ports` must not be set." + diff --git a/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/bad-ns.yaml b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/bad-ns.yaml new file mode 100644 index 000000000..211682121 --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/bad-ns.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Namespace +metadata: + annotations: + foo: bar + linkerd.io/inject: disabled + name: ld-meshinj-badns01 +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + foo: bar + name: ld-meshinj-badns02 +--- +apiVersion: v1 +kind: Namespace +metadata: + name: ld-meshinj-badns03 \ No newline at end of file diff --git a/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/chainsaw-test.yaml b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..84d387eca --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: require-linkerd-mesh-injection +spec: + steps: + - name: step-01 + try: + - apply: + file: ../require-linkerd-mesh-injection.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: require-linkerd-mesh-injection + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: good-ns.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-ns.yaml diff --git a/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/good-ns.yaml b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/good-ns.yaml new file mode 100644 index 000000000..649948782 --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/good-ns.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Namespace +metadata: + annotations: + foo: bar + linkerd.io/inject: enabled + name: ld-meshinj-goodns01 +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + linkerd.io/inject: enabled + foo: bar + name: ld-meshinj-goodns02 \ No newline at end of file diff --git a/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/policy-ready.yaml b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..0a6966bd9 --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-linkerd-mesh-injection +status: + ready: true diff --git a/linkerd-cel/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml b/linkerd-cel/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8c009f0b0 --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,26 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: require-linkerd-mesh-injection +policies: +- ../require-linkerd-mesh-injection.yaml +resources: +- ../.chainsaw-test/bad-ns.yaml +- ../.chainsaw-test/good-ns.yaml +results: +- policy: require-linkerd-mesh-injection + rule: require-mesh-annotation + kind: Namespace + resources: + - ld-meshinj-badns01 + - ld-meshinj-badns02 + - ld-meshinj-badns03 + result: fail +- policy: require-linkerd-mesh-injection + rule: require-mesh-annotation + kind: Namespace + resources: + - ld-meshinj-goodns01 + - ld-meshinj-goodns02 + result: pass + diff --git a/linkerd-cel/require-linkerd-mesh-injection/artifacthub-pkg.yml b/linkerd-cel/require-linkerd-mesh-injection/artifacthub-pkg.yml new file mode 100644 index 000000000..647ab852c --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: require-linkerd-mesh-injection-cel +version: 1.0.0 +displayName: Require Linkerd Mesh Injection in CEL expressions +description: >- + Sidecar proxy injection in Linkerd may be handled at the Namespace level by setting the annotation `linkerd.io/inject` to `enabled`. This policy enforces that all Namespaces contain the annotation `linkerd.io/inject` set to `enabled`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/linkerd-cel/require-linkerd-mesh-injection/require-linkerd-mesh-injection.yaml + ``` +keywords: + - kyverno + - Linkerd + - CEL Expressions +readme: | + Sidecar proxy injection in Linkerd may be handled at the Namespace level by setting the annotation `linkerd.io/inject` to `enabled`. This policy enforces that all Namespaces contain the annotation `linkerd.io/inject` set to `enabled`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Linkerd in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Namespace, Annotation" +digest: 54785b725fde31418dffca17c8b9eb619c64db8351743d370b5f628e5235fd93 +createdAt: "2024-05-21T16:06:15Z" diff --git a/linkerd-cel/require-linkerd-mesh-injection/require-linkerd-mesh-injection.yaml b/linkerd-cel/require-linkerd-mesh-injection/require-linkerd-mesh-injection.yaml new file mode 100644 index 000000000..d05c38ec6 --- /dev/null +++ b/linkerd-cel/require-linkerd-mesh-injection/require-linkerd-mesh-injection.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-linkerd-mesh-injection + annotations: + policies.kyverno.io/title: Require Linkerd Mesh Injection in CEL expressions + policies.kyverno.io/category: Linkerd in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Namespace, Annotation + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Sidecar proxy injection in Linkerd may be handled at the Namespace level by + setting the annotation `linkerd.io/inject` to `enabled`. This policy enforces that + all Namespaces contain the annotation `linkerd.io/inject` set to `enabled`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: require-mesh-annotation + match: + any: + - resources: + kinds: + - Namespace + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "has(object.metadata.annotations) && 'linkerd.io/inject' in object.metadata.annotations && object.metadata.annotations['linkerd.io/inject'] == 'enabled'" + message: "All Namespaces must set the annotation `linkerd.io/inject` to `enabled`." + diff --git a/linkerd/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml b/linkerd/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml index 119385e9d..876c42be2 100644 --- a/linkerd/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml +++ b/linkerd/prevent-linkerd-pod-injection-override/.chainsaw-test/good-podcontrollers.yaml @@ -49,6 +49,9 @@ spec: jobTemplate: spec: template: + metadata: + labels: + app: busybox spec: containers: - name: hello diff --git a/linkerd/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml b/linkerd/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..123a46aa0 --- /dev/null +++ b/linkerd/prevent-linkerd-pod-injection-override/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,51 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-linkerd-pod-injection-override +policies: +- ../prevent-linkerd-pod-injection-override.yaml +resources: +- ../.chainsaw-test/bad-pod.yaml +- ../.chainsaw-test/bad-podcontrollers.yaml +- ../.chainsaw-test/good-pod.yaml +- ../.chainsaw-test/good-podcontrollers.yaml +results: +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Pod + resources: + - badpod01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Deployment + resources: + - baddeploy01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: CronJob + resources: + - badcronjob01 + result: fail +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-linkerd-pod-injection-override + rule: pod-injection-override + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass \ No newline at end of file diff --git a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml index 730df5cbc..1d3b1cbc3 100644 --- a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml +++ b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-pod.yaml @@ -3,7 +3,7 @@ kind: Pod metadata: annotations: foo: bar - config.linkerd.io/skip-inbound-ports: true + config.linkerd.io/skip-inbound-ports: "true" name: badpod01 spec: containers: @@ -14,7 +14,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - config.linkerd.io/skip-outbound-ports: true + config.linkerd.io/skip-outbound-ports: "true" foo: bar name: badpod02 spec: @@ -27,8 +27,8 @@ kind: Pod metadata: annotations: foo: bar - config.linkerd.io/skip-outbound-ports: true - config.linkerd.io/skip-inbound-ports: true + config.linkerd.io/skip-outbound-ports: "true" + config.linkerd.io/skip-inbound-ports: "true" name: badpod03 spec: containers: diff --git a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml index f414b7893..3d4093257 100644 --- a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml +++ b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/bad-podcontrollers.yaml @@ -15,7 +15,7 @@ spec: app: busybox annotations: foo: bar - config.linkerd.io/skip-inbound-ports: true + config.linkerd.io/skip-inbound-ports: "true" spec: containers: - name: busybox @@ -37,7 +37,7 @@ spec: labels: app: busybox annotations: - config.linkerd.io/skip-outbound-ports: true + config.linkerd.io/skip-outbound-ports: "true" foo: bar spec: containers: @@ -61,8 +61,8 @@ spec: app: busybox annotations: foo: bar - config.linkerd.io/skip-inbound-ports: true - config.linkerd.io/skip-outbound-ports: true + config.linkerd.io/skip-inbound-ports: "true" + config.linkerd.io/skip-outbound-ports: "true" spec: containers: - name: busybox @@ -79,7 +79,7 @@ spec: template: metadata: annotations: - config.linkerd.io/skip-outbound-ports: true + config.linkerd.io/skip-outbound-ports: "true" foo: bar spec: containers: @@ -102,7 +102,7 @@ spec: metadata: annotations: foo: bar - config.linkerd.io/skip-inbound-ports: true + config.linkerd.io/skip-inbound-ports: "true" spec: containers: - name: hello @@ -124,8 +124,8 @@ spec: metadata: annotations: foo: bar - config.linkerd.io/skip-outbound-ports: true - config.linkerd.io/skip-inbound-ports: true + config.linkerd.io/skip-outbound-ports: "true" + config.linkerd.io/skip-inbound-ports: "true" spec: containers: - name: hello diff --git a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml index d1605961a..e8c4c6706 100644 --- a/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml +++ b/linkerd/prevent-linkerd-port-skipping/.chainsaw-test/good-podcontrollers.yaml @@ -49,6 +49,9 @@ spec: jobTemplate: spec: template: + metadata: + labels: + app: busybox spec: containers: - name: hello diff --git a/linkerd/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml b/linkerd/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..3eef768b6 --- /dev/null +++ b/linkerd/prevent-linkerd-port-skipping/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,58 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-linkerd-port-skipping +policies: +- ../prevent-linkerd-port-skipping.yaml +resources: +- ../.chainsaw-test/bad-pod.yaml +- ../.chainsaw-test/bad-podcontrollers.yaml +- ../.chainsaw-test/good-pod.yaml +- ../.chainsaw-test/good-podcontrollers.yaml +results: +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Pod + resources: + - badpod01 + - badpod02 + - badpod03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Deployment + resources: + - baddeploy01 + - baddeploy02 + - baddeploy03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: CronJob + resources: + - badcronjob01 + - badcronjob02 + - badcronjob03 + result: fail +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-linkerd-port-skipping + rule: pod-prevent-port-skipping + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass + diff --git a/linkerd/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml b/linkerd/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8c009f0b0 --- /dev/null +++ b/linkerd/require-linkerd-mesh-injection/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,26 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: require-linkerd-mesh-injection +policies: +- ../require-linkerd-mesh-injection.yaml +resources: +- ../.chainsaw-test/bad-ns.yaml +- ../.chainsaw-test/good-ns.yaml +results: +- policy: require-linkerd-mesh-injection + rule: require-mesh-annotation + kind: Namespace + resources: + - ld-meshinj-badns01 + - ld-meshinj-badns02 + - ld-meshinj-badns03 + result: fail +- policy: require-linkerd-mesh-injection + rule: require-mesh-annotation + kind: Namespace + resources: + - ld-meshinj-goodns01 + - ld-meshinj-goodns02 + result: pass + diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/chainsaw-test.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..f8d331033 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,30 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: disallow-ingress-nginx-custom-snippets +spec: + steps: + - name: step-01 + try: + - apply: + file: ../disallow-ingress-nginx-custom-snippets.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: cm-good.yaml + - apply: + file: ig-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: cm-bad.yaml + - apply: + expect: + - check: + ($error != null): true + file: ig-bad.yaml diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-bad.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-bad.yaml new file mode 100644 index 000000000..177ac0678 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-bad.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +data: + allow-snippet-annotations: "true" +kind: ConfigMap +metadata: + name: config-map-true diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-good.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-good.yaml new file mode 100644 index 000000000..6ec1541ac --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/cm-good.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +data: + allow-snippet-annotations: "false" +kind: ConfigMap +metadata: + name: config-map-false +--- +apiVersion: v1 +data: + random: "someval" +kind: ConfigMap +metadata: + name: config-map-other +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-map-empty \ No newline at end of file diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-bad.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-bad.yaml new file mode 100644 index 000000000..82c289e7c --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-bad.yaml @@ -0,0 +1,63 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + foo: bar + nginx.org/server-snippet: | + location / { + return 302 /coffee; + } + nginx.org/location-snippet: | + add_header my-test-header test-value; +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress + annotations: + nginx.org/server-snippet: | + location / { + return 302 /coffee; + } + nginx.org/location-snippet: | + add_header my-test-header test-value; + foo: bar +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-good.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-good.yaml new file mode 100644 index 000000000..37a7cec08 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/ig-good.yaml @@ -0,0 +1,50 @@ + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + foo: bar +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/policy-ready.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..8419e2c67 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-ingress-nginx-custom-snippets +status: + ready: true \ No newline at end of file diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/kyverno-test.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..d668087bf --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,35 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: disallow_nginx_custom_snippets +policies: +- ../disallow-ingress-nginx-custom-snippets.yaml +resources: +- resources.yaml +results: +- kind: ConfigMap + policy: disallow-ingress-nginx-custom-snippets + resources: + - config-map-true + result: fail + rule: check-config-map +- kind: ConfigMap + policy: disallow-ingress-nginx-custom-snippets + resources: + - config-map-false + - config-map-other + - config-map-empty + result: pass + rule: check-config-map +- kind: Ingress + policy: disallow-ingress-nginx-custom-snippets + resources: + - cafe-ingress-with-snippets + result: fail + rule: check-ingress-annotations +- kind: Ingress + policy: disallow-ingress-nginx-custom-snippets + resources: + - cafe-ingress + result: pass + rule: check-ingress-annotations diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/resources.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/resources.yaml new file mode 100644 index 000000000..062f1f953 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/.kyverno-test/resources.yaml @@ -0,0 +1,81 @@ +--- +apiVersion: v1 +data: + allow-snippet-annotations: "false" +kind: ConfigMap +metadata: + name: config-map-false +--- +apiVersion: v1 +data: + allow-snippet-annotations: "true" +kind: ConfigMap +metadata: + name: config-map-true +--- +apiVersion: v1 +data: + random: "someval" +kind: ConfigMap +metadata: + name: config-map-other +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-map-empty +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + nginx.org/server-snippet: | + location / { + return 302 /coffee; + } + nginx.org/location-snippet: | + add_header my-test-header test-value; +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/artifacthub-pkg.yml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/artifacthub-pkg.yml new file mode 100644 index 000000000..1aa414fe7 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: disallow-ingress-nginx-custom-snippets-cel +version: 1.0.0 +displayName: Disallow Custom Snippets in CEL expressions +description: >- + Users that can create or update ingress objects can use the custom snippets feature to obtain all secrets in the cluster (CVE-2021-25742). This policy disables allow-snippet-annotations in the ingress-nginx configuration and blocks *-snippet annotations on an Ingress. See: https://github.com/kubernetes/ingress-nginx/issues/7837 +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml + ``` +keywords: + - kyverno + - Security + - NGINX Ingress + - CEL Expressions +readme: | + Users that can create or update ingress objects can use the custom snippets feature to obtain all secrets in the cluster (CVE-2021-25742). This policy disables allow-snippet-annotations in the ingress-nginx configuration and blocks *-snippet annotations on an Ingress. See: https://github.com/kubernetes/ingress-nginx/issues/7837 + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Security, NGINX Ingress in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "ConfigMap, Ingress" +digest: aaf1d6d140eb40ced231f9b1c1e58c76eb89c1974def85df5f0152b72b8d398b +createdAt: "2024-05-21T16:14:12Z" diff --git a/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml new file mode 100644 index 000000000..e7a098251 --- /dev/null +++ b/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml @@ -0,0 +1,49 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-ingress-nginx-custom-snippets + annotations: + policies.kyverno.io/title: Disallow Custom Snippets in CEL expressions + policies.kyverno.io/category: Security, NGINX Ingress in CEL + policies.kyverno.io/subject: ConfigMap, Ingress + policies.kyverno.io/minversion: "1.11.0" + kyverno.io/kyverno-version: "1.11.0" + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Users that can create or update ingress objects can use the custom snippets + feature to obtain all secrets in the cluster (CVE-2021-25742). This policy + disables allow-snippet-annotations in the ingress-nginx configuration and + blocks *-snippet annotations on an Ingress. + See: https://github.com/kubernetes/ingress-nginx/issues/7837 +spec: + validationFailureAction: Enforce + rules: + - name: check-config-map + match: + any: + - resources: + kinds: + - ConfigMap + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "!has(object.data) || !('allow-snippet-annotations' in object.data) || object.data['allow-snippet-annotations'] == 'false'" + message: "ingress-nginx allow-snippet-annotations must be set to false" + - name: check-ingress-annotations + match: + any: + - resources: + kinds: + - networking.k8s.io/v1/Ingress + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "!has(object.metadata.annotations) || !object.metadata.annotations.exists(annotation, annotation.endsWith('-snippet'))" + message: "ingress-nginx custom snippets are not allowed" + diff --git a/nginx-ingress-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..587740382 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: restrict-annotations +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-annotations.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ig-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ig-bad.yaml diff --git a/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-bad.yaml b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-bad.yaml new file mode 100644 index 000000000..fd98e54ca --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-bad.yaml @@ -0,0 +1,129 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + nginx.org/bad: "alias; " +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + nginx.org/bad: " root ;" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: etc-passwd + annotations: + nginx.org/bad: "/etc/passwd" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: var-run-secrets + annotations: + nginx.org/bad: "/var/run/secrets" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: lua + annotations: + nginx.org/bad: "*! _by_lua 8010-191091" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-good.yaml b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-good.yaml new file mode 100644 index 000000000..1f0b3a8ec --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/ig-good.yaml @@ -0,0 +1,49 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress-with-snippets + annotations: + nginx.org/good: "value" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cafe-ingress +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..3e2289190 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-annotations +status: + ready: true \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml b/nginx-ingress-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..231768b29 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,26 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-annotations +policies: +- ../restrict-annotations.yaml +resources: +- resources.yaml +results: +- kind: Ingress + policy: restrict-annotations + resources: + - alias + - root + - etc-passwd + - var-run-secrets + - lua + result: fail + rule: check-ingress +- kind: Ingress + policy: restrict-annotations + resources: + - no-annotations + - good-annotations + result: pass + rule: check-ingress diff --git a/nginx-ingress-cel/restrict-annotations/.kyverno-test/resources.yaml b/nginx-ingress-cel/restrict-annotations/.kyverno-test/resources.yaml new file mode 100644 index 000000000..ed12c4972 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/.kyverno-test/resources.yaml @@ -0,0 +1,180 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: no-annotations +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: good-annotations + annotations: + nginx.org/good: "value" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: alias + annotations: + nginx.org/bad: "alias; " +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: root + annotations: + nginx.org/bad: " root ;" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: etc-passwd + annotations: + nginx.org/bad: "/etc/passwd" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: var-run-secrets + annotations: + nginx.org/bad: "/var/run/secrets" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: lua + annotations: + nginx.org/bad: "*! _by_lua 8010-191091" +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-annotations/artifacthub-pkg.yml b/nginx-ingress-cel/restrict-annotations/artifacthub-pkg.yml new file mode 100644 index 000000000..f56be90e7 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-annotations-cel +version: 1.0.0 +displayName: Restrict NGINX Ingress annotation values in CEL expressions +description: >- + This policy mitigates CVE-2021-25746 by restricting `metadata.annotations` to safe values. See: https://github.com/kubernetes/ingress-nginx/blame/main/internal/ingress/inspector/rules.go. This issue has been fixed in NGINX Ingress v1.2.0. For NGINX Ingress version 1.0.5+ the "annotation-value-word-blocklist" configuration setting is also recommended. Please refer to the CVE for details. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml + ``` +keywords: + - kyverno + - Security + - NGINX Ingress + - CEL Expressions +readme: | + This policy mitigates CVE-2021-25746 by restricting `metadata.annotations` to safe values. See: https://github.com/kubernetes/ingress-nginx/blame/main/internal/ingress/inspector/rules.go. This issue has been fixed in NGINX Ingress v1.2.0. For NGINX Ingress version 1.0.5+ the "annotation-value-word-blocklist" configuration setting is also recommended. Please refer to the CVE for details. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Security, NGINX Ingress in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Ingress" +digest: 1d65f2c381b323065215afcbc0c0dfaf42b5a3485c4b90ad8dd5035a6f331914 +createdAt: "2024-05-22T06:47:38Z" diff --git a/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml b/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml new file mode 100644 index 000000000..cf61a4ac9 --- /dev/null +++ b/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml @@ -0,0 +1,44 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-annotations + annotations: + policies.kyverno.io/title: Restrict NGINX Ingress annotation values in CEL expressions + policies.kyverno.io/category: Security, NGINX Ingress in CEL + policies.kyverno.io/severity: high + policies.kyverno.io/subject: Ingress + policies.kyverno.io/minversion: "1.11.0" + kyverno.io/kyverno-version: "1.11.0" + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + This policy mitigates CVE-2021-25746 by restricting `metadata.annotations` to safe values. + See: https://github.com/kubernetes/ingress-nginx/blame/main/internal/ingress/inspector/rules.go. + This issue has been fixed in NGINX Ingress v1.2.0. For NGINX Ingress version 1.0.5+ the + "annotation-value-word-blocklist" configuration setting is also recommended. + Please refer to the CVE for details. +spec: + validationFailureAction: Enforce + rules: + - name: check-ingress + match: + any: + - resources: + kinds: + - networking.k8s.io/v1/Ingress + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + !has(object.metadata.annotations) || + ( + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*alias\\s*.*;')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*root\\s*.*;')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/etc/(passwd|shadow|group|nginx|ingress-controller)')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/var/run/secrets')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('.*_by_lua.*')) + ) + message: "spec.rules[].http.paths[].path value is not allowed" + diff --git a/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/chainsaw-test.yaml b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..1a716aa8c --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: restrict-ingress-paths +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-ingress-paths.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ig-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ig-bad.yaml diff --git a/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml new file mode 100644 index 000000000..b3874294d --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml @@ -0,0 +1,85 @@ + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-root +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /root + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-secrets +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /var/run/secrets + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc-kubernetes +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /etc/kubernetes/admin.conf + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-serviceaccount +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /var/run/kubernetes/serviceaccount + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc +spec: + rules: + - host: example.com + http: + paths: + - path: /etc/config + pathType: Prefix + backend: + service: + name: nginx-service + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-good.yaml b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-good.yaml new file mode 100644 index 000000000..a0d35da2b --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/ig-good.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: good-paths +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/policy-ready.yaml b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..d172b2aef --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-paths +status: + ready: true \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml b/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..bde8a7d90 --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,25 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-annotations +policies: +- ../restrict-ingress-paths.yaml +resources: +- resources.yaml +results: +- kind: Ingress + policy: restrict-ingress-paths + resources: + - bad-path-root + - bad-path-etc + - bad-path-etc-kubernetes + - bad-path-serviceaccount + - bad-path-secrets + result: fail + rule: check-paths +- kind: Ingress + policy: restrict-ingress-paths + resources: + - good-paths + result: pass + rule: check-paths diff --git a/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/resources.yaml b/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/resources.yaml new file mode 100644 index 000000000..f413946e8 --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/.kyverno-test/resources.yaml @@ -0,0 +1,109 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: good-paths +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /tea + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 + - path: /coffee + pathType: Prefix + backend: + service: + name: coffee-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-root +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /root + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-secrets +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /var/run/secrets + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc-kubernetes +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /etc/kubernetes/admin.conf + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-serviceaccount +spec: + rules: + - host: cafe.example.com + http: + paths: + - path: /var/run/kubernetes/serviceaccount + pathType: Prefix + backend: + service: + name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc +spec: + rules: + - host: example.com + http: + paths: + - path: /etc/config + pathType: Prefix + backend: + service: + name: nginx-service + port: + number: 80 \ No newline at end of file diff --git a/nginx-ingress-cel/restrict-ingress-paths/artifacthub-pkg.yml b/nginx-ingress-cel/restrict-ingress-paths/artifacthub-pkg.yml new file mode 100644 index 000000000..6dc7c651c --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-ingress-paths-cel +version: 1.0.0 +displayName: Restrict NGINX Ingress path values in CEL expressions +description: >- + This policy mitigates CVE-2021-25745 by restricting `spec.rules[].http.paths[].path` to safe values. Additional paths can be added as required. This issue has been fixed in NGINX Ingress v1.2.0. Please refer to the CVE for details. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml + ``` +keywords: + - kyverno + - Security + - NGINX Ingress + - CEL Expressions +readme: | + This policy mitigates CVE-2021-25745 by restricting `spec.rules[].http.paths[].path` to safe values. Additional paths can be added as required. This issue has been fixed in NGINX Ingress v1.2.0. Please refer to the CVE for details. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Security, NGINX Ingress in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Ingress" +digest: 1c95fe0afc73a2e5e30376d7594d98b4e58cfd21378e3ea10035742eb960220f +createdAt: "2024-05-22T07:13:08Z" diff --git a/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml b/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml new file mode 100644 index 000000000..efabf6062 --- /dev/null +++ b/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml @@ -0,0 +1,40 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-paths + annotations: + policies.kyverno.io/title: Restrict NGINX Ingress path values in CEL expressions + policies.kyverno.io/category: Security, NGINX Ingress in CEL + policies.kyverno.io/severity: high + policies.kyverno.io/subject: Ingress + policies.kyverno.io/minversion: "1.11.0" + kyverno.io/kyverno-version: "1.11.0" + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + This policy mitigates CVE-2021-25745 by restricting `spec.rules[].http.paths[].path` to safe values. + Additional paths can be added as required. This issue has been fixed in NGINX Ingress v1.2.0. + Please refer to the CVE for details. +spec: + validationFailureAction: Enforce + rules: + - name: check-paths + match: + any: + - resources: + kinds: + - networking.k8s.io/v1/Ingress + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + !has(object.spec.rules) || + object.spec.rules.all(rule, !has(rule.http) || !has(rule.http.paths) || + rule.http.paths.all(p, + !p.path.contains('/etc') && !p.path.contains('/var/run/secrets') && + !p.path.contains('/root') && !p.path.contains('/var/run/kubernetes/serviceaccount') && + !p.path.contains('/etc/kubernetes/admin.conf'))) + message: "spec.rules[].http.paths[].path value is not allowed" + diff --git a/nginx-ingress/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml b/nginx-ingress/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml index b3d09bddb..b3874294d 100644 --- a/nginx-ingress/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml +++ b/nginx-ingress/restrict-ingress-paths/.chainsaw-test/ig-bad.yaml @@ -36,7 +36,7 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: bad-path-etc + name: bad-path-etc-kubernetes spec: rules: - host: cafe.example.com @@ -64,5 +64,22 @@ spec: backend: service: name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc +spec: + rules: + - host: example.com + http: + paths: + - path: /etc/config + pathType: Prefix + backend: + service: + name: nginx-service port: number: 80 \ No newline at end of file diff --git a/nginx-ingress/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml b/nginx-ingress/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml index c57aa2a7e..bde8a7d90 100644 --- a/nginx-ingress/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml +++ b/nginx-ingress/restrict-ingress-paths/.kyverno-test/kyverno-test.yaml @@ -12,6 +12,7 @@ results: resources: - bad-path-root - bad-path-etc + - bad-path-etc-kubernetes - bad-path-serviceaccount - bad-path-secrets result: fail diff --git a/nginx-ingress/restrict-ingress-paths/.kyverno-test/resources.yaml b/nginx-ingress/restrict-ingress-paths/.kyverno-test/resources.yaml index 849b672e9..f413946e8 100644 --- a/nginx-ingress/restrict-ingress-paths/.kyverno-test/resources.yaml +++ b/nginx-ingress/restrict-ingress-paths/.kyverno-test/resources.yaml @@ -60,7 +60,7 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: bad-path-etc + name: bad-path-etc-kubernetes spec: rules: - host: cafe.example.com @@ -88,5 +88,22 @@ spec: backend: service: name: tea-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bad-path-etc +spec: + rules: + - host: example.com + http: + paths: + - path: /etc/config + pathType: Prefix + backend: + service: + name: nginx-service port: number: 80 \ No newline at end of file diff --git a/openshift-cel/check-routes/.chainsaw-test/chainsaw-test.yaml b/openshift-cel/check-routes/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..14b19b50c --- /dev/null +++ b/openshift-cel/check-routes/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: check-routes +spec: + steps: + - name: step-01 + try: + - apply: + file: ../check-routes.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: route-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: route-bad.yaml diff --git a/openshift-cel/check-routes/.chainsaw-test/policy-ready.yaml b/openshift-cel/check-routes/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..7620a92af --- /dev/null +++ b/openshift-cel/check-routes/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-routes +status: + ready: true \ No newline at end of file diff --git a/openshift-cel/check-routes/.chainsaw-test/route-bad.yaml b/openshift-cel/check-routes/.chainsaw-test/route-bad.yaml new file mode 100644 index 000000000..9411e209e --- /dev/null +++ b/openshift-cel/check-routes/.chainsaw-test/route-bad.yaml @@ -0,0 +1,12 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: hello-openshift-http +spec: + host: hello-openshift-hello-openshift.mydomain + port: + targetPort: 8080 + to: + kind: Service + name: hello-openshift +--- \ No newline at end of file diff --git a/openshift-cel/check-routes/.chainsaw-test/route-good.yaml b/openshift-cel/check-routes/.chainsaw-test/route-good.yaml new file mode 100644 index 000000000..c9ee97efe --- /dev/null +++ b/openshift-cel/check-routes/.chainsaw-test/route-good.yaml @@ -0,0 +1,66 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: frontend +spec: + host: www.example.com + to: + kind: Service + name: frontend + tls: + termination: reencrypt + key: |- + -----BEGIN PRIVATE KEY----- + [...] + -----END PRIVATE KEY----- + certificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + caCertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + destinationCACertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: frontend-edge +spec: + host: www.example.com + to: + kind: Service + name: frontend + tls: + termination: edge + key: |- + -----BEGIN PRIVATE KEY----- + [...] + -----END PRIVATE KEY----- + certificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + caCertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: route-passthrough-secured +spec: + host: www.example.com + port: + targetPort: 8080 + tls: + termination: passthrough + insecureEdgeTerminationPolicy: None + to: + kind: Service + name: frontend diff --git a/openshift-cel/check-routes/.kyverno-test/kyverno-test.yaml b/openshift-cel/check-routes/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..caf9d781b --- /dev/null +++ b/openshift-cel/check-routes/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,23 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-routes +policies: +- ../check-routes.yaml +resources: +- resources.yaml +results: +- kind: Route + policy: check-routes + resources: + - hello-openshift-http + result: fail + rule: require-tls-routes +- kind: Route + policy: check-routes + resources: + - frontend + - frontend-edge + - route-passthrough-secured + result: pass + rule: require-tls-routes diff --git a/openshift-cel/check-routes/.kyverno-test/resources.yaml b/openshift-cel/check-routes/.kyverno-test/resources.yaml new file mode 100644 index 000000000..dd21c42b5 --- /dev/null +++ b/openshift-cel/check-routes/.kyverno-test/resources.yaml @@ -0,0 +1,78 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: hello-openshift-http +spec: + host: hello-openshift-hello-openshift.mydomain + port: + targetPort: 8080 + to: + kind: Service + name: hello-openshift +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: frontend +spec: + host: www.example.com + to: + kind: Service + name: frontend + tls: + termination: reencrypt + key: |- + -----BEGIN PRIVATE KEY----- + [...] + -----END PRIVATE KEY----- + certificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + caCertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + destinationCACertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: frontend-edge +spec: + host: www.example.com + to: + kind: Service + name: frontend + tls: + termination: edge + key: |- + -----BEGIN PRIVATE KEY----- + [...] + -----END PRIVATE KEY----- + certificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- + caCertificate: |- + -----BEGIN CERTIFICATE----- + [...] + -----END CERTIFICATE----- +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: route-passthrough-secured +spec: + host: www.example.com + port: + targetPort: 8080 + tls: + termination: passthrough + insecureEdgeTerminationPolicy: None + to: + kind: Service + name: frontend diff --git a/openshift-cel/check-routes/artifacthub-pkg.yml b/openshift-cel/check-routes/artifacthub-pkg.yml new file mode 100644 index 000000000..2eb85d6da --- /dev/null +++ b/openshift-cel/check-routes/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: check-routes-cel +version: 1.0.0 +displayName: Require TLS routes in OpenShift in CEL expressions +description: >- + HTTP traffic is not encrypted and hence insecure. This policy prevents configuration of OpenShift HTTP routes. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/openshift-cel/check-routes/check-routes.yaml + ``` +keywords: + - kyverno + - OpenShift + - CEL Expressions +readme: | + HTTP traffic is not encrypted and hence insecure. This policy prevents configuration of OpenShift HTTP routes. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "OpenShift in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Route" +digest: ac5ffb379d599adbf5ec0f2b08c76539b696645f6dee7a05f4b9a75b939243f8 +createdAt: "2024-05-22T07:21:10Z" diff --git a/openshift-cel/check-routes/check-routes.yaml b/openshift-cel/check-routes/check-routes.yaml new file mode 100644 index 000000000..7ec6e0d43 --- /dev/null +++ b/openshift-cel/check-routes/check-routes.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-routes + annotations: + policies.kyverno.io/title: Require TLS routes in OpenShift in CEL expressions + policies.kyverno.io/category: OpenShift in CEL expressions + policies.kyverno.io/severity: high + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: Route + policies.kyverno.io/description: |- + HTTP traffic is not encrypted and hence insecure. This policy prevents configuration of OpenShift HTTP routes. +spec: + validationFailureAction: Enforce + background: true + rules: + - name: require-tls-routes + match: + any: + - resources: + kinds: + - route.openshift.io/v1/Route + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "has(object.spec.tls)" + message: >- + HTTP routes are not allowed. Configure TLS for secure routes. + diff --git a/openshift-cel/disallow-deprecated-apis/.kyverno-test/kyverno-test.yaml b/openshift-cel/disallow-deprecated-apis/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8d17d1927 --- /dev/null +++ b/openshift-cel/disallow-deprecated-apis/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,33 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-routes +policies: +- ../disallow-deprecated-apis.yaml +resources: +- resources.yaml +results: +- kind: ClusterRole + policy: disallow-deprecated-apis + resources: + - openshift-cluster-role-deprecated + result: fail + rule: check-deprecated-apis +- kind: ClusterRoleBinding + policy: disallow-deprecated-apis + resources: + - openshift-cluster-role-binding-deprecated + result: fail + rule: check-deprecated-apis +- kind: Role + policy: disallow-deprecated-apis + resources: + - openshift-role-deprecated + result: fail + rule: check-deprecated-apis +- kind: RoleBinding + policy: disallow-deprecated-apis + resources: + - openshift-role-binding-deprecated + result: fail + rule: check-deprecated-apis diff --git a/openshift-cel/disallow-deprecated-apis/.kyverno-test/resources.yaml b/openshift-cel/disallow-deprecated-apis/.kyverno-test/resources.yaml new file mode 100644 index 000000000..5f37e352a --- /dev/null +++ b/openshift-cel/disallow-deprecated-apis/.kyverno-test/resources.yaml @@ -0,0 +1,89 @@ +apiVersion: authorization.openshift.io/v1 +kind: ClusterRole +metadata: + name: openshift-cluster-role-deprecated +spec: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +apiVersion: authorization.openshift.io/v1 +kind: ClusterRoleBinding +metadata: + name: openshift-cluster-role-binding-deprecated +subjects: +- kind: User + name: jane # "name" is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: openshift-cluster-role-deprecated + apiGroup: authorization.openshift.io/v1 +--- +apiVersion: authorization.openshift.io/v1 +kind: Role +metadata: + name: openshift-role-deprecated +spec: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +apiVersion: authorization.openshift.io/v1 +kind: RoleBinding +metadata: + name: openshift-role-binding-deprecated + namespace: default +subjects: +- kind: User + name: jane # "name" is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: openshift-role-deprecated + apiGroup: authorization.openshift.io/v1 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: openshift-cluster-role-valid +spec: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: openshift-cluster-role-binding +subjects: +- kind: User + name: jane # "name" is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: openshift-cluster-role + apiGroup: rbac.authorization.k8s.io/v1 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: openshift-role +spec: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: openshift-role-binding + namespace: default +subjects: +- kind: User + name: jane # "name" is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: openshift-role + apiGroup: rbac.authorization.k8s.io/v1 diff --git a/openshift-cel/disallow-deprecated-apis/artifacthub-pkg.yml b/openshift-cel/disallow-deprecated-apis/artifacthub-pkg.yml new file mode 100644 index 000000000..7cf0c78f2 --- /dev/null +++ b/openshift-cel/disallow-deprecated-apis/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: disallow-deprecated-apis-cel +version: 1.0.0 +displayName: Disallow deprecated APIs in CEL expressions +description: >- + OpenShift APIs are sometimes deprecated and removed after a few releases. As a best practice, older API versions should be replaced with newer versions. This policy validates for APIs that are deprecated or scheduled for removal. Note that checking for some of these resources may require modifying the Kyverno ConfigMap to remove filters. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/openshift-cel/disallow-deprecated-apis/disallow-deprecated-apis.yaml + ``` +keywords: + - kyverno + - OpenShift + - CEL Expressions +readme: | + OpenShift APIs are sometimes deprecated and removed after a few releases. As a best practice, older API versions should be replaced with newer versions. This policy validates for APIs that are deprecated or scheduled for removal. Note that checking for some of these resources may require modifying the Kyverno ConfigMap to remove filters. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "OpenShift in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "ClusterRole,ClusterRoleBinding,Role,RoleBinding,RBAC" +digest: 8ca91e6472908c67621b07b800023ff5e93383dbd9fd2d0f90879506cec45dd7 +createdAt: "2024-05-22T07:36:55Z" diff --git a/openshift-cel/disallow-deprecated-apis/disallow-deprecated-apis.yaml b/openshift-cel/disallow-deprecated-apis/disallow-deprecated-apis.yaml new file mode 100644 index 000000000..984f03178 --- /dev/null +++ b/openshift-cel/disallow-deprecated-apis/disallow-deprecated-apis.yaml @@ -0,0 +1,41 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-deprecated-apis + annotations: + policies.kyverno.io/title: Disallow deprecated APIs in CEL expressions + policies.kyverno.io/category: OpenShift in CEL + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: ClusterRole,ClusterRoleBinding,Role,RoleBinding,RBAC + policies.kyverno.io/description: >- + OpenShift APIs are sometimes deprecated and removed after a few releases. + As a best practice, older API versions should be replaced with newer versions. + This policy validates for APIs that are deprecated or scheduled for removal. + Note that checking for some of these resources may require modifying the Kyverno + ConfigMap to remove filters. +spec: + validationFailureAction: Enforce + background: true + rules: + - name: check-deprecated-apis + match: + any: + - resources: + kinds: + - authorization.openshift.io/v1/ClusterRole + - authorization.openshift.io/v1/ClusterRoleBinding + - authorization.openshift.io/v1/Role + - authorization.openshift.io/v1/RoleBinding + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "false" + messageExpression: >- + object.apiVersion + '/' + object.kind + ' is deprecated.' + diff --git a/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/kyverno-test.yaml b/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..4aadc467a --- /dev/null +++ b/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,23 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-policy +policies: +- ../disallow-jenkins-pipeline-strategy.yaml +resources: +- resources.yaml +results: +- kind: BuildConfig + policy: disallow-jenkins-pipeline-strategy + resources: + - sample-jenkins-pipeline + - sample-jenkins-pipeline-new + result: fail + rule: check-build-strategy +- kind: BuildConfig + policy: disallow-jenkins-pipeline-strategy + resources: + - sample-pipeline-no-jenkins + - sample-pipeline-no-jenkins-new + result: pass + rule: check-build-strategy diff --git a/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/resources.yaml b/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/resources.yaml new file mode 100644 index 000000000..335e2e20d --- /dev/null +++ b/openshift-cel/disallow-jenkins-pipeline-strategy/.kyverno-test/resources.yaml @@ -0,0 +1,43 @@ +kind: "BuildConfig" +apiVersion: "v1" +metadata: + name: "sample-jenkins-pipeline" +spec: + source: + git: + uri: "https://github.com/openshift/ruby-hello-world" + strategy: + jenkinsPipelineStrategy: + jenkinsfilePath: some/repo/dir/filename +--- +kind: "BuildConfig" +apiVersion: "v1" +metadata: + name: "sample-pipeline-no-jenkins" +spec: + source: + git: + uri: "https://github.com/openshift/ruby-hello-world" + strategy: {} +--- +kind: "BuildConfig" +apiVersion: "build.openshift.io/v1" +metadata: + name: "sample-jenkins-pipeline-new" +spec: + source: + git: + uri: "https://github.com/openshift/ruby-hello-world" + strategy: + jenkinsPipelineStrategy: + jenkinsfilePath: some/repo/dir/filename +--- +kind: "BuildConfig" +apiVersion: "build.openshift.io/v1" +metadata: + name: "sample-pipeline-no-jenkins-new" +spec: + source: + git: + uri: "https://github.com/openshift/ruby-hello-world" + strategy: {} diff --git a/openshift-cel/disallow-jenkins-pipeline-strategy/artifacthub-pkg.yml b/openshift-cel/disallow-jenkins-pipeline-strategy/artifacthub-pkg.yml new file mode 100644 index 000000000..10065d31e --- /dev/null +++ b/openshift-cel/disallow-jenkins-pipeline-strategy/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: disallow-jenkins-pipeline-strategy-cel +version: 1.0.0 +displayName: Disallow OpenShift Jenkins Pipeline Build Strategy in CEL expressions +description: >- + The Jenkins Pipeline Build Strategy has been deprecated. This policy prevents its use. Use OpenShift Pipelines instead. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/openshift-cel/disallow-jenkins-pipeline-strategy/disallow-jenkins-pipeline-strategy.yaml + ``` +keywords: + - kyverno + - OpenShift + - CEL Expressions +readme: | + The Jenkins Pipeline Build Strategy has been deprecated. This policy prevents its use. Use OpenShift Pipelines instead. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "OpenShift in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "BuildConfig" +digest: f38131a30e03d633c0745ae181e83c75ae94a180d1e0402a8cba26ccf8088f81 +createdAt: "2024-05-22T09:40:45Z" diff --git a/openshift-cel/disallow-jenkins-pipeline-strategy/disallow-jenkins-pipeline-strategy.yaml b/openshift-cel/disallow-jenkins-pipeline-strategy/disallow-jenkins-pipeline-strategy.yaml new file mode 100644 index 000000000..2857aa488 --- /dev/null +++ b/openshift-cel/disallow-jenkins-pipeline-strategy/disallow-jenkins-pipeline-strategy.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-jenkins-pipeline-strategy + annotations: + policies.kyverno.io/title: Disallow OpenShift Jenkins Pipeline Build Strategy in CEL expressions + policies.kyverno.io/category: OpenShift in CEL + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: BuildConfig + policies.kyverno.io/description: >- + The Jenkins Pipeline Build Strategy has been deprecated. This policy prevents its use. Use OpenShift Pipelines instead. +spec: + validationFailureAction: Enforce + background: true + rules: + - name: check-build-strategy + match: + any: + - resources: + kinds: + - v1/BuildConfig + - build.openshift.io/v1/BuildConfig + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "!has(object.spec.strategy.jenkinsPipelineStrategy)" + message: >- + Jenkins Pipeline Build Strategy has been deprecated and is not allowed + diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/chainsaw-test.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..2b8304268 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: disallow-security-context-constraint-anyuid +spec: + steps: + - name: step-01 + try: + - apply: + file: ../disallow-security-context-constraint-anyuid.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: roles-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: roles-bad.yaml + - apply: + file: clusterroles-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: clusterroles-bad.yaml + - apply: + file: rb-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: rb-bad.yaml + - apply: + file: crb-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: crb-bad.yaml diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-bad.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-bad.yaml new file mode 100644 index 000000000..8c5bdbd84 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-bad.yaml @@ -0,0 +1,34 @@ + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: crole-bad01 +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: crole-bad02 +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - "*" diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-good.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-good.yaml new file mode 100644 index 000000000..e03d3c81d --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/clusterroles-good.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: crole-good01 +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-bad.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-bad.yaml new file mode 100644 index 000000000..a3ccd78f9 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-bad.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: clusterrolebinding-bad01 +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: system:openshift:scc:anyuid + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-good.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-good.yaml new file mode 100644 index 000000000..b49a62cbf --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/crb-good.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: clusterrolebinding-good01 +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: view + apiGroup: rbac.authorization.k8s.io diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/policy-ready.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..ed6d92cb9 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-security-context-constraint-anyuid +status: + ready: true \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-bad.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-bad.yaml new file mode 100644 index 000000000..378129584 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-bad.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: rolebinding-bad01 +subjects: +- kind: User + name: dave + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: system:openshift:scc:anyuid + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-good.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-good.yaml new file mode 100644 index 000000000..811d5d7c2 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/rb-good.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: rolebinding-good01 +subjects: +- kind: User + name: dave + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: view + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-bad.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-bad.yaml new file mode 100644 index 000000000..984b8cf8b --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-bad.yaml @@ -0,0 +1,35 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pod-role-bad01 +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: default + name: pod-role-bad02 +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - "*" +--- \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-good.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-good.yaml new file mode 100644 index 000000000..34c8d7a54 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.chainsaw-test/roles-good.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: good-role01 +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] \ No newline at end of file diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/kyverno-test.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..36c55e3bf --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,59 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-routes +policies: +- ../disallow-security-context-constraint-anyuid.yaml +resources: +- resources.yaml +results: +- kind: ClusterRole + policy: disallow-security-context-constraint-anyuid + resources: + - secret-reader-anyuid-use + - secret-reader-anyuid-all + result: fail + rule: check-security-context-constraint +- kind: Role + policy: disallow-security-context-constraint-anyuid + resources: + - pod-role-anyuid-use + - pod-role-anyuid-all + result: fail + rule: check-security-context-constraint +- kind: ClusterRole + policy: disallow-security-context-constraint-anyuid + resources: + - secret-reader + result: pass + rule: check-security-context-constraint +- kind: Role + policy: disallow-security-context-constraint-anyuid + resources: + - pod-role + result: pass + rule: check-security-context-constraint +- kind: ClusterRoleBinding + policy: disallow-security-context-constraint-anyuid + resources: + - clusterrolebinding-anyuid + result: fail + rule: check-security-context-roleref +- kind: RoleBinding + policy: disallow-security-context-constraint-anyuid + resources: + - rolebinding-anyuid + result: fail + rule: check-security-context-roleref +- kind: ClusterRoleBinding + policy: disallow-security-context-constraint-anyuid + resources: + - clusterrolebinding-test + result: pass + rule: check-security-context-roleref +- kind: RoleBinding + policy: disallow-security-context-constraint-anyuid + resources: + - rolebinding-test + result: pass + rule: check-security-context-roleref diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/resources.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/resources.yaml new file mode 100644 index 000000000..0ce3f58be --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/.kyverno-test/resources.yaml @@ -0,0 +1,154 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: default + name: pod-role-anyuid-use +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: default + name: pod-role +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: default + name: pod-role-anyuid-all +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - "*" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + # "namespace" omitted since ClusterRoles are not namespaced + name: secret-reader-anyuid-use +rules: +- apiGroups: [""] + # + # at the HTTP level, the name of the resource for accessing Secret + # objects is "secrets" + resources: ["secrets"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + # "namespace" omitted since ClusterRoles are not namespaced + name: secret-reader +rules: +- apiGroups: [""] + # + # at the HTTP level, the name of the resource for accessing Secret + # objects is "secrets" + resources: ["secrets"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + # "namespace" omitted since ClusterRoles are not namespaced + name: secret-reader-anyuid-all +rules: +- apiGroups: [""] + # + # at the HTTP level, the name of the resource for accessing Secret + # objects is "secrets" + resources: ["secrets"] + verbs: ["get", "watch", "list"] +- apiGroups: + - security.openshift.io + resourceNames: + - anyuid + resources: + - securitycontextconstraints + verbs: + - "*" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: rolebinding-anyuid + namespace: development +subjects: +- kind: User + name: dave # Name is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: system:openshift:scc:anyuid + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: clusterrolebinding-anyuid +subjects: +- kind: Group + name: manager # Name is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: system:openshift:scc:anyuid + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: rolebinding-test + namespace: development +subjects: +- kind: User + name: dave # Name is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: view + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: clusterrolebinding-test +subjects: +- kind: Group + name: manager # Name is case sensitive + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: view + apiGroup: rbac.authorization.k8s.io diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/artifacthub-pkg.yml b/openshift-cel/disallow-security-context-constraint-anyuid/artifacthub-pkg.yml new file mode 100644 index 000000000..69839fe57 --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: disallow-security-context-constraint-anyuid-cel +version: 1.0.0 +displayName: Disallow use of the SecurityContextConstraint (SCC) anyuid in CEL expressions +description: >- + Disallow the use of the SecurityContextConstraint (SCC) anyuid which allows a pod to run with the UID as declared in the image instead of a random UID +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/openshift-cel/disallow-security-context-constraint-anyuid/disallow-security-context-constraint-anyuid.yaml + ``` +keywords: + - kyverno + - Security + - CEL Expressions +readme: | + Disallow the use of the SecurityContextConstraint (SCC) anyuid which allows a pod to run with the UID as declared in the image instead of a random UID + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Security in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Role,ClusterRole,RBAC" +digest: a12e5cbb7ee88722774bf06d5c086804b4e3151811088be926470b12b8920cf0 +createdAt: "2024-05-22T09:53:47Z" diff --git a/openshift-cel/disallow-security-context-constraint-anyuid/disallow-security-context-constraint-anyuid.yaml b/openshift-cel/disallow-security-context-constraint-anyuid/disallow-security-context-constraint-anyuid.yaml new file mode 100644 index 000000000..d37d4c72d --- /dev/null +++ b/openshift-cel/disallow-security-context-constraint-anyuid/disallow-security-context-constraint-anyuid.yaml @@ -0,0 +1,51 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-security-context-constraint-anyuid + annotations: + policies.kyverno.io/title: Disallow use of the SecurityContextConstraint (SCC) anyuid in CEL expressions + policies.kyverno.io/category: Security in CEL + policies.kyverno.io/severity: high + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: Role,ClusterRole,RBAC + policies.kyverno.io/description: >- + Disallow the use of the SecurityContextConstraint (SCC) anyuid which allows a pod to run with the UID as declared in the image instead of a random UID +spec: + validationFailureAction: Enforce + background: true + rules: + - name: check-security-context-constraint + match: + any: + - resources: + kinds: + - ClusterRole + - Role + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "!has(object.rules) || !object.rules.exists(rule, 'anyuid' in rule.resourceNames && ('use' in rule.verbs || '*' in rule.verbs))" + message: >- + Use of the SecurityContextConstraint (SCC) anyuid is not allowed + - name: check-security-context-roleref + match: + any: + - resources: + kinds: + - ClusterRoleBinding + - RoleBinding + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "object.roleRef.name != 'system:openshift:scc:anyuid'" + message: >- + Use of the SecurityContextConstraint (SCC) anyuid is not allowed + diff --git a/openshift-cel/enforce-etcd-encryption/.kyverno-test/kyverno-test.yaml b/openshift-cel/enforce-etcd-encryption/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..2cf4b765d --- /dev/null +++ b/openshift-cel/enforce-etcd-encryption/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,21 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-policy +policies: +- ../enforce-etcd-encryption.yaml +resources: +- resources.yaml +results: +- kind: APIServer + policy: enforce-etcd-encryption + resources: + - cluster-no-encryption + result: fail + rule: check-etcd-encryption +- kind: APIServer + policy: enforce-etcd-encryption + resources: + - cluster-with-encryption + result: pass + rule: check-etcd-encryption diff --git a/openshift-cel/enforce-etcd-encryption/.kyverno-test/resources.yaml b/openshift-cel/enforce-etcd-encryption/.kyverno-test/resources.yaml new file mode 100644 index 000000000..442468ad2 --- /dev/null +++ b/openshift-cel/enforce-etcd-encryption/.kyverno-test/resources.yaml @@ -0,0 +1,16 @@ +apiVersion: config.openshift.io/v1 +kind: APIServer +metadata: + annotations: + release.openshift.io/create-only: "true" + name: cluster-no-encryption +spec: {} +--- +apiVersion: config.openshift.io/v1 +kind: APIServer +metadata: + annotations: + release.openshift.io/create-only: "true" + name: cluster-with-encryption +spec: + encryption: {} diff --git a/openshift-cel/enforce-etcd-encryption/artifacthub-pkg.yml b/openshift-cel/enforce-etcd-encryption/artifacthub-pkg.yml new file mode 100644 index 000000000..a5198a02d --- /dev/null +++ b/openshift-cel/enforce-etcd-encryption/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: enforce-etcd-encryption-cel +version: 1.0.0 +displayName: Enforce etcd encryption in OpenShift in CEL expressions +description: >- + Encryption at rest is a security best practice. This policy ensures encryption is enabled for etcd in OpenShift clusters. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/openshift-cel/enforce-etcd-encryption/enforce-etcd-encryption.yaml + ``` +keywords: + - kyverno + - OpenShift + - CEL Expressions +readme: | + Encryption at rest is a security best practice. This policy ensures encryption is enabled for etcd in OpenShift clusters. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "OpenShift in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "APIServer" +digest: 293113b4abad7fea2e4d805bc63dc23c8fad9658424353644e501ac5b0abd592 +createdAt: "2024-05-22T10:15:24Z" diff --git a/openshift-cel/enforce-etcd-encryption/enforce-etcd-encryption.yaml b/openshift-cel/enforce-etcd-encryption/enforce-etcd-encryption.yaml new file mode 100644 index 000000000..045402624 --- /dev/null +++ b/openshift-cel/enforce-etcd-encryption/enforce-etcd-encryption.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: enforce-etcd-encryption + annotations: + policies.kyverno.io/title: Enforce etcd encryption in OpenShift in CEL expressions + policies.kyverno.io/category: OpenShift + policies.kyverno.io/severity: high + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: APIServer + policies.kyverno.io/description: >- + Encryption at rest is a security best practice. This policy ensures encryption is enabled for etcd in OpenShift clusters. +spec: + validationFailureAction: Enforce + background: true + rules: + - name: check-etcd-encryption + match: + any: + - resources: + kinds: + - config.openshift.io/v1/APIServer + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "has(object.spec.encryption)" + message: >- + Encryption should be enabled for etcd + diff --git a/psa-cel/add-psa-namespace-reporting/.chainsaw-test/chainsaw-test.yaml b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/chainsaw-test.yaml new file mode 100644 index 000000000..ed3b2044c --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: add-psa-namespace-reporting +spec: + steps: + - name: apply-policy + try: + - apply: + file: ../add-psa-namespace-reporting.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: add-psa-namespace-reporting + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: apply-policy-test + try: + - apply: + file: namespace-with-psa-labels.yaml + - apply: + expect: + - check: + ($error != null): true + file: namespace-without-psa-labels.yaml diff --git a/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-with-psa-labels.yaml b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-with-psa-labels.yaml new file mode 100644 index 000000000..e94a09e9a --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-with-psa-labels.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test + labels: + pod-security.kubernetes.io/enforce: "privileged" \ No newline at end of file diff --git a/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-without-psa-labels.yaml b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-without-psa-labels.yaml new file mode 100644 index 000000000..7956df12c --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/namespace-without-psa-labels.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-fail \ No newline at end of file diff --git a/psa-cel/add-psa-namespace-reporting/.chainsaw-test/policy-ready.yaml b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..cfb6ab67a --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: add-psa-namespace-reporting +status: + ready: true + + + diff --git a/psa-cel/add-psa-namespace-reporting/.kyverno-test/kyverno-test.yaml b/psa-cel/add-psa-namespace-reporting/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..513ac0fe8 --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,22 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: add-psa-namespace-reporting-tests +policies: +- ../add-psa-namespace-reporting.yaml +resources: +- namespace-with-psa-labels.yaml +- namespace-without-psa-labels.yaml +results: + - kind: Namespace + policy: add-psa-namespace-reporting + resources: + - test + rule: check-namespace-labels + result: pass + - kind: Namespace + policy: add-psa-namespace-reporting + resources: + - test-fail + rule: check-namespace-labels + result: fail \ No newline at end of file diff --git a/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-with-psa-labels.yaml b/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-with-psa-labels.yaml new file mode 100644 index 000000000..e94a09e9a --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-with-psa-labels.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test + labels: + pod-security.kubernetes.io/enforce: "privileged" \ No newline at end of file diff --git a/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-without-psa-labels.yaml b/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-without-psa-labels.yaml new file mode 100644 index 000000000..7956df12c --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/.kyverno-test/namespace-without-psa-labels.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-fail \ No newline at end of file diff --git a/psa-cel/add-psa-namespace-reporting/add-psa-namespace-reporting.yaml b/psa-cel/add-psa-namespace-reporting/add-psa-namespace-reporting.yaml new file mode 100644 index 000000000..94f57bfd2 --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/add-psa-namespace-reporting.yaml @@ -0,0 +1,42 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: add-psa-namespace-reporting + annotations: + policies.kyverno.io/title: Add PSA Namespace Reporting in CEL expressions + policies.kyverno.io/category: Pod Security Admission, EKS Best Practices in CEL + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: Namespace + policies.kyverno.io/description: >- + This policy is valuable as it ensures that all namespaces within a Kubernetes + cluster are labeled with Pod Security Admission (PSA) labels, which are crucial + for defining security levels and ensuring that pods within a namespace operate + under the defined Pod Security Standard (PSS). By enforcing namespace labeling, + This policy audits namespaces to verify the presence of PSA labels. + If a namespace is found without the required labels, it generates and maintain + and ClusterPolicy Report in default namespace. + This helps administrators identify namespaces that do not comply with the + organization's security practices and take appropriate action to rectify the + situation. +spec: + validationFailureAction: Audit + background: true + rules: + - name: check-namespace-labels + match: + any: + - resources: + kinds: + - Namespace + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "has(object.metadata.labels) && object.metadata.labels.exists(label, label.startsWith('pod-security.kubernetes.io/') && object.metadata.labels[label] != '')" + message: This Namespace is missing a PSA label. + diff --git a/psa-cel/add-psa-namespace-reporting/artifacthub-pkg.yml b/psa-cel/add-psa-namespace-reporting/artifacthub-pkg.yml new file mode 100644 index 000000000..0f68883ae --- /dev/null +++ b/psa-cel/add-psa-namespace-reporting/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: add-psa-namespace-reporting-cel +version: 1.0.0 +displayName: Add PSA Namespace Reporting in CEL expressions +description: >- + This policy is valuable as it ensures that all namespaces within a Kubernetes cluster are labeled with Pod Security Admission (PSA) labels, which are crucial for defining security levels and ensuring that pods within a namespace operate under the defined Pod Security Standard (PSS). By enforcing namespace labeling, This policy audits namespaces to verify the presence of PSA labels. If a namespace is found without the required labels, it generates and maintain and ClusterPolicy Report in default namespace. This helps administrators identify namespaces that do not comply with the organization's security practices and take appropriate action to rectify the situation. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/psa-cel/add-psa-namespace-reporting/add-psa-namespace-reporting.yaml + ``` +keywords: + - kyverno + - Pod Security Admission + - EKS Best Practices + - CEL Expressions +readme: | + This policy is valuable as it ensures that all namespaces within a Kubernetes cluster are labeled with Pod Security Admission (PSA) labels, which are crucial for defining security levels and ensuring that pods within a namespace operate under the defined Pod Security Standard (PSS). By enforcing namespace labeling, This policy audits namespaces to verify the presence of PSA labels. If a namespace is found without the required labels, it generates and maintain and ClusterPolicy Report in default namespace. This helps administrators identify namespaces that do not comply with the organization's security practices and take appropriate action to rectify the situation. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Pod Security Admission, EKS Best Practices in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Namespace" +digest: d624eddc7d55bcdb3129ccb57f6e7d840b6eda6cf57134ce7385b89a92ea8686 +createdAt: "2024-05-22T08:30:28Z" diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/chainsaw-test.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..3a62388b2 --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,98 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: deny-privileged-profile +spec: + steps: + - name: step-01 + try: + - apply: + file: ../deny-privileged-profile.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: deny-privileged-profile + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - script: + content: | + #!/bin/bash + set -eu + cp $KUBECONFIG temp + export KUBECONFIG=./temp + export USERNAME=denyprivilegeduser + export CA=ca.crt + #### Get CA certificate from kubeconfig assuming it's the first in the list. + kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 --decode > ./ca.crt + #### Set CLUSTER_SERVER from kubeconfig assuming it's the first in the list. + CLUSTER_SERVER="$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}')" + #### Set CLUSTER from kubeconfig assuming it's the first in the list. + CLUSTER="$(kubectl config view --raw -o jsonpath='{.clusters[0].name}')" + #### Generate private key + openssl genrsa -out $USERNAME.key 2048 + #### Create CSR + openssl req -new -key $USERNAME.key -out $USERNAME.csr -subj "/O=testorg/CN=$USERNAME" + #### Send CSR to kube-apiserver for approval + cat < $USERNAME.crt + #### + #### Create the credential object and output the new kubeconfig file + kubectl config set-credentials $USERNAME --client-certificate=$USERNAME.crt --client-key=$USERNAME.key --embed-certs + #### Set the context + kubectl config set-context $USERNAME-context --user=$USERNAME --cluster=$CLUSTER + # Delete CSR + kubectl delete csr $USERNAME + - apply: + file: cr.yaml + - apply: + file: crb.yaml + - script: + content: | + #!/bin/bash + set -eu + export KUBECONFIG=./temp + kubectl --context=denyprivilegeduser-context create -f ns-good.yaml + - script: + content: | + #!/bin/bash + set -eu + export KUBECONFIG=./temp + if kubectl --context=denyprivilegeduser-context create -f ns-bad.yaml; then exit 1; else exit 0; fi + - sleep: + duration: 5s + finally: + - script: + content: kubectl delete -f ns-good.yaml --ignore-not-found + - script: + content: kubectl delete -f ns-bad.yaml --ignore-not-found + - script: + content: | + set -e + rm ./temp + - name: step-05 + try: + - apply: + file: ns-good.yaml + - apply: + file: ns-bad.yaml diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/cr.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/cr.yaml new file mode 100755 index 000000000..f39afe9fc --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/cr.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ns-deleter +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - create diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/crb.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/crb.yaml new file mode 100755 index 000000000..1f3cc8101 --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/crb.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ns-deleter:denyprivilegeduser +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ns-deleter +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: denyprivilegeduser diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/ns-bad.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/ns-bad.yaml new file mode 100644 index 000000000..21f29bb8b --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/ns-bad.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + pod-security.kubernetes.io/enforce: privileged + name: deny-privileged-bad-ns01 +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + pod-security.kubernetes.io/enforce: privileged + foo: bar + name: deny-privileged-bad-ns02 \ No newline at end of file diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/ns-good.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/ns-good.yaml new file mode 100644 index 000000000..f760fac2c --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/ns-good.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + pod-security.kubernetes.io/enforce: baseline + name: deny-privileged-good-ns01 +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + foo: bar + name: deny-privileged-good-ns02 +--- +apiVersion: v1 +kind: Namespace +metadata: + name: deny-privileged-good-ns03 \ No newline at end of file diff --git a/psa-cel/deny-privileged-profile/.chainsaw-test/policy-ready.yaml b/psa-cel/deny-privileged-profile/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..93dfa2f2d --- /dev/null +++ b/psa-cel/deny-privileged-profile/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: deny-privileged-profile +status: + ready: true diff --git a/psa-cel/deny-privileged-profile/.kyverno-test/kyverno-test.yaml b/psa-cel/deny-privileged-profile/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..6d26b1d82 --- /dev/null +++ b/psa-cel/deny-privileged-profile/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,16 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: deny-privileged-profile +policies: +- ../deny-privileged-profile.yaml +resources: +- ../.chainsaw-test/ns-bad.yaml +results: +- policy: deny-privileged-profile + rule: check-privileged + kind: Namespace + resources: + - deny-privileged-bad-ns01 + - deny-privileged-bad-ns02 + result: fail \ No newline at end of file diff --git a/psa-cel/deny-privileged-profile/artifacthub-pkg.yml b/psa-cel/deny-privileged-profile/artifacthub-pkg.yml new file mode 100644 index 000000000..0a78df882 --- /dev/null +++ b/psa-cel/deny-privileged-profile/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: deny-privileged-profile-cel +version: 1.0.0 +displayName: Deny Privileged Profile in CEL expressions +description: >- + When Pod Security Admission (PSA) is enforced at the cluster level via an AdmissionConfiguration file which defines a default level at baseline or restricted, setting of a label at the `privileged` profile will effectively cause unrestricted workloads in that Namespace, overriding the cluster default. This may effectively represent a circumvention attempt and should be closely controlled. This policy ensures that only those holding the cluster-admin ClusterRole may create Namespaces which assign the label `pod-security.kubernetes.io/enforce=privileged`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/psa-cel/deny-privileged-profile/deny-privileged-profile.yaml + ``` +keywords: + - kyverno + - Pod Security Admission + - CEL Expressions +readme: | + When Pod Security Admission (PSA) is enforced at the cluster level via an AdmissionConfiguration file which defines a default level at baseline or restricted, setting of a label at the `privileged` profile will effectively cause unrestricted workloads in that Namespace, overriding the cluster default. This may effectively represent a circumvention attempt and should be closely controlled. This policy ensures that only those holding the cluster-admin ClusterRole may create Namespaces which assign the label `pod-security.kubernetes.io/enforce=privileged`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Pod Security Admission in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Namespace" +digest: a8eb6c291f91e8ebd2535712413432e0659f2839c0929334e5f69a883506d85a +createdAt: "2024-05-22T08:35:47Z" diff --git a/psa-cel/deny-privileged-profile/deny-privileged-profile.yaml b/psa-cel/deny-privileged-profile/deny-privileged-profile.yaml new file mode 100644 index 000000000..f01dddfee --- /dev/null +++ b/psa-cel/deny-privileged-profile/deny-privileged-profile.yaml @@ -0,0 +1,44 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: deny-privileged-profile + annotations: + policies.kyverno.io/title: Deny Privileged Profile in CEL expressions + policies.kyverno.io/category: Pod Security Admission in CEL expressions + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: Namespace + policies.kyverno.io/description: >- + When Pod Security Admission (PSA) is enforced at the cluster level + via an AdmissionConfiguration file which defines a default level at + baseline or restricted, setting of a label at the `privileged` profile + will effectively cause unrestricted workloads in that Namespace, overriding + the cluster default. This may effectively represent a circumvention attempt + and should be closely controlled. This policy ensures that only those holding + the cluster-admin ClusterRole may create Namespaces which assign the label + `pod-security.kubernetes.io/enforce=privileged`. +spec: + validationFailureAction: Audit + background: false + rules: + - name: check-privileged + match: + any: + - resources: + kinds: + - Namespace + selector: + matchLabels: + pod-security.kubernetes.io/enforce: privileged + exclude: + any: + - clusterRoles: + - cluster-admin + validate: + cel: + expressions: + - expression: "false" + message: Only cluster-admins may create Namespaces that allow setting the privileged level. + diff --git a/psa/deny-privileged-profile/.kyverno-test/kyverno-test.yaml b/psa/deny-privileged-profile/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..6d26b1d82 --- /dev/null +++ b/psa/deny-privileged-profile/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,16 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: deny-privileged-profile +policies: +- ../deny-privileged-profile.yaml +resources: +- ../.chainsaw-test/ns-bad.yaml +results: +- policy: deny-privileged-profile + rule: check-privileged + kind: Namespace + resources: + - deny-privileged-bad-ns01 + - deny-privileged-bad-ns02 + result: fail \ No newline at end of file diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/chainsaw-test.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..82d8a6f91 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,87 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: disallow-default-tlsoptions +spec: + steps: + - name: step-00 + try: + - assert: + file: crd-assert.yaml + - name: step-01 + try: + - apply: + file: ../disallow-default-tlsoptions.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: disallow-default-tlsoptions + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - script: + content: | + #!/bin/bash + set -eu + export USERNAME=tlsoptionsuser + export CA=ca.crt + #### Get CA certificate from kubeconfig assuming it's the first in the list. + kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 --decode > ./ca.crt + #### Set CLUSTER_SERVER from kubeconfig assuming it's the first in the list. + CLUSTER_SERVER="$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}')" + #### Set CLUSTER from kubeconfig assuming it's the first in the list. + CLUSTER="$(kubectl config view --raw -o jsonpath='{.clusters[0].name}')" + #### Generate private key + openssl genrsa -out $USERNAME.key 2048 + #### Create CSR + openssl req -new -key $USERNAME.key -out $USERNAME.csr -subj "/O=testorg/CN=$USERNAME" + #### Send CSR to kube-apiserver for approval + cat < $USERNAME.crt + #### + #### Create the credential object and output the new kubeconfig file + kubectl config set-credentials $USERNAME --client-certificate=$USERNAME.crt --client-key=$USERNAME.key --embed-certs + #### Set the context + kubectl config set-context $USERNAME-context --user=$USERNAME --cluster=$CLUSTER + # Delete CSR + kubectl delete csr $USERNAME + - name: step-03 + try: + - apply: + file: cr.yaml + - apply: + file: crb.yaml + - name: step-04 + try: + - script: + content: if kubectl create --context=tlsoptionsuser-context -f tlsoption.yaml; + then exit 1; else exit 0; fi + - script: + content: kubectl create -f tlsoption.yaml + - name: step-99 + try: + - script: + content: | + kubectl delete -f tlsoption.yaml + kubectl config unset users.tlsoptionsuser + kubectl config unset contexts.tlsoptionsuser-context diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/cr.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/cr.yaml new file mode 100755 index 000000000..28edd3a9a --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/cr.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tlsoptions-creator +rules: +- apiGroups: + - traefik.containo.us + resources: + - tlsoptions + verbs: + - create diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crb.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crb.yaml new file mode 100755 index 000000000..ffcdb7691 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crb.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tlsoptions-creator:tlsoptionsuser +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tlsoptions-creator +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: tlsoptionsuser diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crd-assert.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crd-assert.yaml new file mode 100755 index 000000000..086d560e0 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/crd-assert.yaml @@ -0,0 +1,12 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: tlsoptions.traefik.containo.us +spec: {} +status: + acceptedNames: + kind: TLSOption + plural: tlsoptions + singular: tlsoption + storedVersions: + - v1alpha1 diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/policy-ready.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..f3e37c449 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-default-tlsoptions +status: + ready: true diff --git a/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/tlsoption.yaml b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/tlsoption.yaml new file mode 100644 index 000000000..c38aa643f --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.chainsaw-test/tlsoption.yaml @@ -0,0 +1,21 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: default +spec: + minVersion: VersionTLS12 + maxVersion: VersionTLS13 + curvePreferences: + - CurveP521 + - CurveP384 + cipherSuites: + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_RSA_WITH_AES_256_GCM_SHA384 + clientAuth: + secretNames: + - secret-ca1 + - secret-ca2 + clientAuthType: VerifyClientCertIfGiven + sniStrict: true + alpnProtocols: + - foobar \ No newline at end of file diff --git a/traefik-cel/disallow-default-tlsoptions/.kyverno-test/kyverno-test.yaml b/traefik-cel/disallow-default-tlsoptions/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..445c7aaa5 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,15 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: disallow-default-tlsoptions +policies: +- ../disallow-default-tlsoptions.yaml +resources: +- resource.yaml +results: +- kind: TLSOption + policy: disallow-default-tlsoptions + resources: + - default + result: fail + rule: disallow-default-tlsoptions diff --git a/traefik-cel/disallow-default-tlsoptions/.kyverno-test/resource.yaml b/traefik-cel/disallow-default-tlsoptions/.kyverno-test/resource.yaml new file mode 100644 index 000000000..b7de0f06a --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/.kyverno-test/resource.yaml @@ -0,0 +1,22 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: default + namespace: default +spec: + minVersion: VersionTLS12 + maxVersion: VersionTLS13 + curvePreferences: + - CurveP521 + - CurveP384 + cipherSuites: + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_RSA_WITH_AES_256_GCM_SHA384 + clientAuth: + secretNames: + - secret-ca1 + - secret-ca2 + clientAuthType: VerifyClientCertIfGiven + sniStrict: true + alpnProtocols: + - foobar \ No newline at end of file diff --git a/traefik-cel/disallow-default-tlsoptions/artifacthub-pkg.yml b/traefik-cel/disallow-default-tlsoptions/artifacthub-pkg.yml new file mode 100644 index 000000000..bc588570b --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/artifacthub-pkg.yml @@ -0,0 +1,23 @@ +name: disallow-default-tlsoptions-cel +version: 1.0.0 +displayName: Disallow Default TLSOptions in CEL expressions +description: >- + The TLSOption CustomResource sets cluster-wide TLS configuration options for Traefik when none are specified in a TLS router. Since this can take effect for all Ingress resources, creating the `default` TLSOption is a restricted operation. This policy ensures that only a cluster-admin can create the `default` TLSOption resource. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/traefik-cel/disallow-default-tlsoptions/disallow-default-tlsoptions.yaml + ``` +keywords: + - kyverno + - Traefik + - CEL Expressions +readme: | + The TLSOption CustomResource sets cluster-wide TLS configuration options for Traefik when none are specified in a TLS router. Since this can take effect for all Ingress resources, creating the `default` TLSOption is a restricted operation. This policy ensures that only a cluster-admin can create the `default` TLSOption resource. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Traefik in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "TLSOption" +digest: ddb6b4d4f7a09720499c6ad306b4ee73999003d0fde7d2feb35cb6b19d0c73df +createdAt: "2024-05-22T07:43:46Z" diff --git a/traefik-cel/disallow-default-tlsoptions/disallow-default-tlsoptions.yaml b/traefik-cel/disallow-default-tlsoptions/disallow-default-tlsoptions.yaml new file mode 100644 index 000000000..d09b5ad55 --- /dev/null +++ b/traefik-cel/disallow-default-tlsoptions/disallow-default-tlsoptions.yaml @@ -0,0 +1,37 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-default-tlsoptions + annotations: + policies.kyverno.io/title: Disallow Default TLSOptions in CEL expressions + policies.kyverno.io/category: Traefik in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: TLSOption + kyverno.io/kyverno-version: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + The TLSOption CustomResource sets cluster-wide TLS configuration options for Traefik when + none are specified in a TLS router. Since this can take effect for all Ingress resources, + creating the `default` TLSOption is a restricted operation. This policy ensures that + only a cluster-admin can create the `default` TLSOption resource. +spec: + validationFailureAction: Audit + background: false + rules: + - name: disallow-default-tlsoptions + match: + any: + - resources: + names: + - default + kinds: + - TLSOption + exclude: + clusterRoles: + - cluster-admin + validate: + cel: + expressions: + - expression: "false" + message: "Only cluster administrators are allowed to set default TLSOptions." +