diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43fa88d1d..da15d9e01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,6 +58,7 @@ jobs: - ^other$/^re[c-q] - ^other-cel$/^re[c-q] - ^other$/^res + - ^other-cel$/^res - ^other$/^[s-z] - ^pod-security$ - ^pod-security-cel$ diff --git a/other-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..55aef1211 --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,39 @@ +# 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 + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-annotations + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pod-bad.yaml + - apply: + file: podcontroller-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: podcontroller-bad.yaml + diff --git a/other-cel/restrict-annotations/.chainsaw-test/pod-bad.yaml b/other-cel/restrict-annotations/.chainsaw-test/pod-bad.yaml new file mode 100644 index 000000000..e273f217b --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/pod-bad.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + fluxcd.io/foo: bar + name: badpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + bar: foo + fluxcd.io/foo: bar + foo: bar + name: badpod02 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + bar: foo + fluxcd.io/hello: bar + foo: bar + name: badpod03 +spec: + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-annotations/.chainsaw-test/pod-good.yaml b/other-cel/restrict-annotations/.chainsaw-test/pod-good.yaml new file mode 100644 index 000000000..9cb7d4668 --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/pod-good.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goodpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + bar: foo + flux.io/foo: bar + foo: bar + name: goodpod02 +spec: + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-annotations/.chainsaw-test/podcontroller-bad.yaml b/other-cel/restrict-annotations/.chainsaw-test/podcontroller-bad.yaml new file mode 100644 index 000000000..abd918f2f --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/podcontroller-bad.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + fluxcd.io/foo: bar + labels: + app: busybox + name: baddeployment01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + strategy: {} + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + annotations: + foo: bar + fluxcd.io/foo: bar + bar: foo + name: badcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: busybox + image: busybox:1.35 + restartPolicy: OnFailure + diff --git a/other-cel/restrict-annotations/.chainsaw-test/podcontroller-good.yaml b/other-cel/restrict-annotations/.chainsaw-test/podcontroller-good.yaml new file mode 100644 index 000000000..8995b0c41 --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/podcontroller-good.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + flux.io/foo: bar + labels: + app: busybox + name: gooddeployment01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + strategy: {} + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + annotations: + foo: bar + name: goodcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: busybox + image: busybox:1.35 + restartPolicy: OnFailure + diff --git a/other-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..9643a7fce --- /dev/null +++ b/other-cel/restrict-annotations/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-annotations +status: + ready: true + diff --git a/other-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..3ba9c58e4 --- /dev/null +++ b/other-cel/restrict-annotations/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,28 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-annotations +policies: +- ../restrict-annotations.yaml +resources: +- resource.yaml +results: +- kind: Deployment + policy: restrict-annotations + resources: + - mydeploy + result: fail + rule: block-flux-v1 +- kind: Pod + policy: restrict-annotations + resources: + - myapp-pod + result: fail + rule: block-flux-v1 +- kind: CronJob + policy: restrict-annotations + resources: + - hello + result: pass + rule: block-flux-v1 + diff --git a/other-cel/restrict-annotations/.kyverno-test/resource.yaml b/other-cel/restrict-annotations/.kyverno-test/resource.yaml new file mode 100644 index 000000000..7879734db --- /dev/null +++ b/other-cel/restrict-annotations/.kyverno-test/resource.yaml @@ -0,0 +1,54 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + app: myapp + name: myapp-pod + annotations: + fluxcd.io/title: Annotation for pods +spec: + containers: + - image: nginx + name: myapp-pod + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: myapp + name: mydeploy + annotations: + fluxcd.io/title: Annotation for deployment +spec: + replicas: 1 + selector: + matchLabels: + app: myapp + template: + metadata: + labels: + app: myapp + spec: + containers: + - image: nginx + name: nginx + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: hello + annotations: + gauss.io/title: Annotation for CronJob +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: hello + image: busybox + restartPolicy: OnFailure + diff --git a/other-cel/restrict-annotations/artifacthub-pkg.yml b/other-cel/restrict-annotations/artifacthub-pkg.yml new file mode 100644 index 000000000..3a789bbff --- /dev/null +++ b/other-cel/restrict-annotations/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-annotations-cel +version: 1.0.0 +displayName: Restrict Annotations in CEL expressions +description: >- + Some annotations control functionality driven by other cluster-wide tools and are not normally set by some class of users. This policy prevents the use of an annotation beginning with `fluxcd.io/`. This can be useful to ensure users either don't set reserved annotations or to force them to use a newer version of an annotation. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-annotations/restrict-annotations.yaml + ``` +keywords: + - kyverno + - Sample + - CEL Expressions +readme: | + Some annotations control functionality driven by other cluster-wide tools and are not normally set by some class of users. This policy prevents the use of an annotation beginning with `fluxcd.io/`. This can be useful to ensure users either don't set reserved annotations or to force them to use a newer version of an annotation. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Sample in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod, Annotation" +digest: 55b4953e1ca6aa6038d407aae539705d9a8c1136d2ffc277df1686a08ac7c9a8 +createdAt: "2024-04-12T15:55:04Z" + diff --git a/other-cel/restrict-annotations/restrict-annotations.yaml b/other-cel/restrict-annotations/restrict-annotations.yaml new file mode 100644 index 000000000..84f7df771 --- /dev/null +++ b/other-cel/restrict-annotations/restrict-annotations.yaml @@ -0,0 +1,37 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-annotations + annotations: + policies.kyverno.io/title: Restrict Annotations in CEL expressions + policies.kyverno.io/category: Sample in CEL + policies.kyverno.io/minversion: 1.11.0 + policies.kyverno.io/subject: Pod, Annotation + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Some annotations control functionality driven by other cluster-wide tools and are not + normally set by some class of users. This policy prevents the use of an annotation beginning + with `fluxcd.io/`. This can be useful to ensure users either + don't set reserved annotations or to force them to use a newer version of an annotation. + pod-policies.kyverno.io/autogen-controllers: none +spec: + validationFailureAction: Audit + background: true + rules: + - name: block-flux-v1 + match: + any: + - resources: + kinds: + - Deployment + - CronJob + - Job + - StatefulSet + - DaemonSet + - Pod + validate: + cel: + expressions: + - expression: "!has(object.metadata.annotations) || !object.metadata.annotations.exists(annotation, annotation.startsWith('fluxcd.io/'))" + message: Cannot use Flux v1 annotation. + diff --git a/other-cel/restrict-binding-clusteradmin/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..2393d32be --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,39 @@ +# 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-binding-clusteradmin +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-binding-clusteradmin.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-binding-clusteradmin + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - 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/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-bad.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-bad.yaml new file mode 100644 index 000000000..d358dcad7 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-bad.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: badcrb01 +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: badcrb02 +subjects: +- kind: ServiceAccount + namespace: foo + name: manager +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-good.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-good.yaml new file mode 100644 index 000000000..613294872 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/crb-good.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: goodcrb01 +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: secret-reader + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: goodcrb02 +subjects: +- kind: ServiceAccount + namespace: foo + name: manager +roleRef: + kind: ClusterRole + name: foo-reader + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-clusteradmin/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..ef3124247 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-binding-clusteradmin +status: + ready: true + diff --git a/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-bad.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-bad.yaml new file mode 100644 index 000000000..f367b8335 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-bad.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: badrb01 +subjects: +- kind: User + name: foo + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: badrb02 +subjects: +- kind: ServiceAccount + name: foo + namespace: foo +roleRef: + kind: Role + name: cluster-admin + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-good.yaml b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-good.yaml new file mode 100644 index 000000000..9308e707a --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.chainsaw-test/rb-good.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: goodrb01 +subjects: +- kind: User + name: foo + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo-bar + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: goodrb02 +subjects: +- kind: ServiceAccount + name: foo + namespace: foo +roleRef: + kind: Role + name: foo-bar + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8b2670ad9 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,41 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-binding-clusteradmin +policies: +- ../restrict-binding-clusteradmin.yaml +resources: +- ../.chainsaw-test/crb-bad.yaml +- ../.chainsaw-test/crb-good.yaml +- ../.chainsaw-test/rb-bad.yaml +- ../.chainsaw-test/rb-good.yaml +results: +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: ClusterRoleBinding + resources: + - badcrb01 + - badcrb02 + result: fail +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + result: pass +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: RoleBinding + resources: + - badrb01 + - badrb02 + result: fail +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + result: pass + diff --git a/other-cel/restrict-binding-clusteradmin/artifacthub-pkg.yml b/other-cel/restrict-binding-clusteradmin/artifacthub-pkg.yml new file mode 100644 index 000000000..68478d905 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-binding-clusteradmin-cel +version: 1.0.0 +displayName: Restrict Binding to Cluster-Admin in CEL expressions +description: >- + The cluster-admin ClusterRole allows any action to be performed on any resource in the cluster and its granting should be heavily restricted. This policy prevents binding to the cluster-admin ClusterRole in RoleBinding or ClusterRoleBinding resources. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-binding-clusteradmin/restrict-binding-clusteradmin.yaml + ``` +keywords: + - kyverno + - Security + - CEL Expressions +readme: | + The cluster-admin ClusterRole allows any action to be performed on any resource in the cluster and its granting should be heavily restricted. This policy prevents binding to the cluster-admin ClusterRole in RoleBinding or ClusterRoleBinding resources. + + 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: "RoleBinding, ClusterRoleBinding, RBAC" +digest: 313ef33ca553700424ca8c1dde5572219a1ef976a78138e78a6c5838f8a11d2c +createdAt: "2024-04-12T16:00:17Z" + diff --git a/other-cel/restrict-binding-clusteradmin/restrict-binding-clusteradmin.yaml b/other-cel/restrict-binding-clusteradmin/restrict-binding-clusteradmin.yaml new file mode 100644 index 000000000..ef831d656 --- /dev/null +++ b/other-cel/restrict-binding-clusteradmin/restrict-binding-clusteradmin.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-binding-clusteradmin + annotations: + policies.kyverno.io/title: Restrict Binding to Cluster-Admin in CEL expressions + policies.kyverno.io/category: Security in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: RoleBinding, ClusterRoleBinding, RBAC + 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/description: >- + The cluster-admin ClusterRole allows any action to be performed on any resource + in the cluster and its granting should be heavily restricted. This + policy prevents binding to the cluster-admin ClusterRole in + RoleBinding or ClusterRoleBinding resources. +spec: + validationFailureAction: Audit + background: true + rules: + - name: clusteradmin-bindings + match: + any: + - resources: + kinds: + - RoleBinding + - ClusterRoleBinding + validate: + cel: + expressions: + - expression: "object.roleRef.name != 'cluster-admin'" + message: "Binding to cluster-admin is not allowed." + diff --git a/other-cel/restrict-binding-system-groups/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..614464468 --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,39 @@ +# 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-binding-system-groups +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-binding-system-groups.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-binding-system-groups + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - 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/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml new file mode 100644 index 000000000..e7fca387d --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml @@ -0,0 +1,41 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: badcrb01 +subjects: +- kind: Group + name: "system:anonymous" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: badcrb02 +subjects: +- kind: Group + namespace: foo + name: "system:unauthenticated" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: badcrb03 +subjects: +- kind: Group + namespace: foo + name: "system:masters" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-good.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-good.yaml new file mode 100644 index 000000000..6dfc7360f --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/crb-good.yaml @@ -0,0 +1,40 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: goodcrb01 +subjects: +- kind: Group + name: secret-reader + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: goodcrb02 +subjects: +- kind: ServiceAccount + namespace: foo + name: foo-reader +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: goodcrb03 +subjects: +- kind: ServiceAccount + namespace: foo + name: "system.foo" +roleRef: + kind: ClusterRole + name: manager + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-system-groups/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..badf5a0e7 --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-binding-system-groups +status: + ready: true + diff --git a/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-bad.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-bad.yaml new file mode 100644 index 000000000..963f4cbc6 --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-bad.yaml @@ -0,0 +1,41 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: badrb01 +subjects: +- kind: Group + name: "system:anonymous" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: badrb02 +subjects: +- kind: Group + name: "system:unauthenticated" + namespace: foo + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: badrb03 +subjects: +- kind: Group + name: "system:masters" + namespace: foo + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-good.yaml b/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-good.yaml new file mode 100644 index 000000000..fa1225bc6 --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.chainsaw-test/rb-good.yaml @@ -0,0 +1,39 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: goodrb01 +subjects: +- kind: User + name: foo + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo-bar + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: goodrb02 +subjects: +- kind: ServiceAccount + name: foo + namespace: foo +roleRef: + kind: Role + name: foo-bar + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: goodrb03 +subjects: +- kind: Group + name: "system:foo" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: foo + apiGroup: rbac.authorization.k8s.io + diff --git a/other-cel/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..1b34b1e91 --- /dev/null +++ b/other-cel/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,45 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-binding-system-groups +policies: +- ../restrict-binding-system-groups.yaml +resources: +- ../.chainsaw-test/crb-bad.yaml +- ../.chainsaw-test/crb-good.yaml +- ../.chainsaw-test/rb-bad.yaml +- ../.chainsaw-test/rb-good.yaml +results: +- policy: restrict-binding-system-groups + rule: restrict-subject-groups + kind: ClusterRoleBinding + resources: + - badcrb01 + - badcrb02 + - badcrb03 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-subject-groups + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + - goodcrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-subject-groups + kind: RoleBinding + resources: + - badrb01 + - badrb02 + - badrb03 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-subject-groups + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + - goodrb03 + result: pass + diff --git a/other-cel/restrict-binding-system-groups/artifacthub-pkg.yml b/other-cel/restrict-binding-system-groups/artifacthub-pkg.yml new file mode 100644 index 000000000..b3f76a92b --- /dev/null +++ b/other-cel/restrict-binding-system-groups/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +name: restrict-binding-system-groups-cel +version: 1.0.0 +displayName: Restrict Binding System Groups in CEL expressions +description: >- + Certain system groups exist in Kubernetes which grant permissions that are used for certain system-level functions yet typically never appropriate for other users. This policy prevents creating bindings to some of these groups including system:anonymous, system:unauthenticated, and system:masters. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-binding-system-groups/restrict-binding-system-groups.yaml + ``` +keywords: + - kyverno + - Security + - EKS Best Practices + - CEL Expressions +readme: | + Certain system groups exist in Kubernetes which grant permissions that are used for certain system-level functions yet typically never appropriate for other users. This policy prevents creating bindings to some of these groups including system:anonymous, system:unauthenticated, and system:masters. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Security, EKS Best Practices in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "RoleBinding, ClusterRoleBinding, RBAC" +digest: 9843fd8b6e7357bc01ccbfcd3280bc3bc1d8baa5da4dce46c7d0125906a8efdc +createdAt: "2024-04-12T16:28:28Z" + diff --git a/other-cel/restrict-binding-system-groups/restrict-binding-system-groups.yaml b/other-cel/restrict-binding-system-groups/restrict-binding-system-groups.yaml new file mode 100644 index 000000000..1b9e1a91b --- /dev/null +++ b/other-cel/restrict-binding-system-groups/restrict-binding-system-groups.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-binding-system-groups + annotations: + policies.kyverno.io/title: Restrict Binding System Groups in CEL expressions + policies.kyverno.io/category: Security, EKS Best Practices in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: RoleBinding, ClusterRoleBinding, RBAC + 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/description: >- + Certain system groups exist in Kubernetes which grant permissions that + are used for certain system-level functions yet typically never appropriate + for other users. This policy prevents creating bindings to some of these + groups including system:anonymous, system:unauthenticated, and system:masters. +spec: + validationFailureAction: Audit + background: true + rules: + - name: restrict-subject-groups + match: + any: + - resources: + kinds: + - RoleBinding + - ClusterRoleBinding + validate: + cel: + expressions: + - expression: "object.subjects.all(subject, subject.name != 'system:anonymous')" + message: "Binding to system:anonymous is not allowed." + - expression: "object.subjects.all(subject, subject.name != 'system:unauthenticated')" + message: "Binding to system:unauthenticated is not allowed." + - expression: "object.subjects.all(subject, subject.name != 'system:masters')" + message: "Binding to system:masters is not allowed." + diff --git a/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..5e299aa72 --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# 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-clusterrole-nodesproxy +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-clusterrole-nodesproxy.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-clusterrole-nodesproxy + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: cr-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: cr-bad.yaml + diff --git a/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-bad.yaml b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-bad.yaml new file mode 100644 index 000000000..630cd4da2 --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-bad.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr01 +rules: +- apiGroups: [""] + resources: ["nodes/proxy", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr02 +rules: +- apiGroups: [""] + resources: ["pods", "nodes/proxy"] + verbs: ["get", "watch", "list"] + diff --git a/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-good.yaml b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-good.yaml new file mode 100644 index 000000000..fa3403cdc --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/cr-good.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodcr01 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodcr02 +rules: +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "watch", "list"] + diff --git a/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..70e535108 --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-clusterrole-nodesproxy +status: + ready: true + diff --git a/other-cel/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..9a119fe0d --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,25 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-clusterrole-nodesproxy +policies: +- ../restrict-clusterrole-nodesproxy.yaml +resources: +- ../.chainsaw-test/cr-bad.yaml +- ../.chainsaw-test/cr-good.yaml +results: +- policy: restrict-clusterrole-nodesproxy + rule: clusterrole-nodesproxy + kind: ClusterRole + resources: + - badcr01 + - badcr02 + result: fail +- policy: restrict-clusterrole-nodesproxy + rule: clusterrole-nodesproxy + kind: ClusterRole + resources: + - goodcr01 + - goodcr02 + result: pass + diff --git a/other-cel/restrict-clusterrole-nodesproxy/artifacthub-pkg.yml b/other-cel/restrict-clusterrole-nodesproxy/artifacthub-pkg.yml new file mode 100644 index 000000000..8d44e34aa --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-clusterrole-nodesproxy-cel +version: 1.0.0 +displayName: Restrict ClusterRole with Nodes Proxy in CEL expressions +description: >- + A ClusterRole with nodes/proxy resource access allows a user to perform anything the kubelet API allows. It also allows users to bypass the API server and talk directly to the kubelet potentially circumventing audits and admission controllers. See https://blog.aquasec.com/privilege-escalation-kubernetes-rbac for more info. This policy prevents the creation of a ClusterRole if it contains the nodes/proxy resource. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-clusterrole-nodesproxy/restrict-clusterrole-nodesproxy.yaml + ``` +keywords: + - kyverno + - Sample + - CEL Expressions +readme: | + A ClusterRole with nodes/proxy resource access allows a user to perform anything the kubelet API allows. It also allows users to bypass the API server and talk directly to the kubelet potentially circumventing audits and admission controllers. See https://blog.aquasec.com/privilege-escalation-kubernetes-rbac for more info. This policy prevents the creation of a ClusterRole if it contains the nodes/proxy resource. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Sample in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "ClusterRole, RBAC" +digest: 54304b50ebe12dab7f36afa09eaadf5f591d39a2bfe3ee83c150df30cbf66c4b +createdAt: "2024-04-13T16:12:56Z" + diff --git a/other-cel/restrict-clusterrole-nodesproxy/restrict-clusterrole-nodesproxy.yaml b/other-cel/restrict-clusterrole-nodesproxy/restrict-clusterrole-nodesproxy.yaml new file mode 100644 index 000000000..a3aad1c3f --- /dev/null +++ b/other-cel/restrict-clusterrole-nodesproxy/restrict-clusterrole-nodesproxy.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-clusterrole-nodesproxy + annotations: + policies.kyverno.io/title: Restrict ClusterRole with Nodes Proxy in CEL expressions + policies.kyverno.io/category: Sample in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: ClusterRole, RBAC + 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/description: >- + A ClusterRole with nodes/proxy resource access allows a user to + perform anything the kubelet API allows. It also allows users to bypass + the API server and talk directly to the kubelet potentially circumventing + audits and admission controllers. See https://blog.aquasec.com/privilege-escalation-kubernetes-rbac + for more info. This policy prevents the creation + of a ClusterRole if it contains the nodes/proxy resource. +spec: + validationFailureAction: Audit + background: true + rules: + - name: clusterrole-nodesproxy + match: + any: + - resources: + kinds: + - ClusterRole + validate: + cel: + expressions: + - expression: >- + !object.rules.exists(rule, + rule.resources.exists(resource, resource == 'nodes/proxy') && + rule.apiGroups.exists(apiGroup, apiGroup == '')) + message: "A ClusterRole containing the nodes/proxy resource is not allowed." + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..418a7bed3 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,39 @@ +# 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-controlplane-scheduling +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-controlplane-scheduling.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-controlplane-scheduling + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pod-bad.yaml + - apply: + file: podcontroller-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: podcontroller-bad.yaml + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-bad.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-bad.yaml new file mode 100644 index 000000000..48a871abc --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-bad.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Pod +metadata: + name: badpod01 + labels: + app: myapp +spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod02 + labels: + app: myapp +spec: + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Exists" + effect: "NoSchedule" + - key: "foo" + operator: "Equal" + value: "bar" + effect: "NoExecute" + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-good.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-good.yaml new file mode 100644 index 000000000..55da85360 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/pod-good.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goodpod01 + labels: + app: myapp +spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: goodpod02 + labels: + app: myapp +spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/foo-bar" + operator: "Equal" + value: "bar" + effect: "NoExecute" + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-bad.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-bad.yaml new file mode 100644 index 000000000..5d00d7481 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-bad.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: baddeployment01 +spec: + replicas: 1 + selector: + matchLabels: + foo: bar + template: + metadata: + labels: + foo: bar + spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Exists" + effect: "NoSchedule" + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + restartPolicy: OnFailure + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-good.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-good.yaml new file mode 100644 index 000000000..28a6a0f7a --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/podcontroller-good.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gooddeployment01 +spec: + replicas: 1 + selector: + matchLabels: + foo: bar + template: + metadata: + labels: + foo: bar + spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/foo-bar" + operator: "Equal" + value: "bar" + effect: "NoExecute" + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + tolerations: + - key: "node-role.kubernetes.io/foo-bar" + operator: "Equal" + value: "bar" + effect: "NoExecute" + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + restartPolicy: OnFailure + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-controlplane-scheduling/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..0bf44690a --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-controlplane-scheduling +status: + ready: true + diff --git a/other-cel/restrict-controlplane-scheduling/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-controlplane-scheduling/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..298a91b15 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,24 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-controlplane-scheduling +policies: +- ../restrict-controlplane-scheduling.yaml +resources: +- resource.yaml +results: +- kind: Pod + policy: restrict-controlplane-scheduling + resources: + - default/badpod01 + - default/badpod02 + result: fail + rule: restrict-controlplane-scheduling-master +- kind: Pod + policy: restrict-controlplane-scheduling + resources: + - default/goodpod01 + - default/goodpod02 + result: pass + rule: restrict-controlplane-scheduling-master + diff --git a/other-cel/restrict-controlplane-scheduling/.kyverno-test/resource.yaml b/other-cel/restrict-controlplane-scheduling/.kyverno-test/resource.yaml new file mode 100644 index 000000000..56f1d6e43 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/.kyverno-test/resource.yaml @@ -0,0 +1,69 @@ +apiVersion: v1 +kind: Pod +metadata: + name: badpod01 + labels: + app: myapp +spec: + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + nodeSelector: + kubernetes.io/hostname: minikube + containers: + - image: nginx + name: pod + restartPolicy: Always + +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod02 + labels: + app: myapp +spec: + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + nodeSelector: + kubernetes.io/hostname: minikube + containers: + - image: nginx + name: pod + restartPolicy: Always +--- +apiVersion: v1 +kind: Pod +metadata: + name: goodpod01 + labels: + app: myapp +spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: goodpod02 + labels: + app: myapp +spec: + tolerations: + - key: "foo-bar" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/foo-bar" + operator: "Equal" + value: "bar" + effect: "NoExecute" + containers: + - name: busybox + image: busybox:1.35 + diff --git a/other-cel/restrict-controlplane-scheduling/artifacthub-pkg.yml b/other-cel/restrict-controlplane-scheduling/artifacthub-pkg.yml new file mode 100644 index 000000000..4cdf099f3 --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-controlplane-scheduling-cel +version: 1.0.0 +displayName: Restrict control plane scheduling in CEL expressions +description: >- + Scheduling non-system Pods to control plane nodes (which run kubelet) is often undesirable because it takes away resources from the control plane components and can represent a possible security threat vector. This policy prevents users from setting a toleration in a Pod spec which allows running on control plane nodes with the taint key `node-role.kubernetes.io/master`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-controlplane-scheduling/restrict-controlplane-scheduling.yaml + ``` +keywords: + - kyverno + - Sample + - CEL Expressions +readme: | + Scheduling non-system Pods to control plane nodes (which run kubelet) is often undesirable because it takes away resources from the control plane components and can represent a possible security threat vector. This policy prevents users from setting a toleration in a Pod spec which allows running on control plane nodes with the taint key `node-role.kubernetes.io/master`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Sample in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod" +digest: 55668531abc1c98763bcfac82efd6bb912c37fbf5b0f8cf68dc09fd0c24b6ce9 +createdAt: "2024-04-13T16:19:01Z" + diff --git a/other-cel/restrict-controlplane-scheduling/restrict-controlplane-scheduling.yaml b/other-cel/restrict-controlplane-scheduling/restrict-controlplane-scheduling.yaml new file mode 100644 index 000000000..41e83b84d --- /dev/null +++ b/other-cel/restrict-controlplane-scheduling/restrict-controlplane-scheduling.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-controlplane-scheduling + annotations: + policies.kyverno.io/title: Restrict control plane scheduling in CEL expressions + policies.kyverno.io/category: Sample in CEL + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Scheduling non-system Pods to control plane nodes (which run kubelet) is often undesirable + because it takes away resources from the control plane components and can represent + a possible security threat vector. This policy prevents users from setting a toleration + in a Pod spec which allows running on control plane nodes + with the taint key `node-role.kubernetes.io/master`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: restrict-controlplane-scheduling-master + match: + any: + - resources: + kinds: + - Pod + validate: + cel: + expressions: + - expression: >- + !has(object.spec.tolerations) || + !object.spec.tolerations.exists(toleration, has(toleration.key) && toleration.key in ['node-role.kubernetes.io/master', 'node-role.kubernetes.io/control-plane']) + message: Pods may not use tolerations which schedule on control plane nodes. + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..55da6024c --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,35 @@ +# 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-deprecated-registry +spec: + # disable templating because it can cause issues with CEL expressions + template: false + steps: + - name: step-01 + try: + - apply: + file: ../restrict-deprecated-registry.yaml + - apply: + file: ns.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pod-bad.yaml + - apply: + file: podcontroller-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: podcontroller-bad.yaml + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/ns.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/ns.yaml new file mode 100644 index 000000000..2d9245781 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/ns.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: dep-registry-ns + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-bad.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-bad.yaml new file mode 100644 index 000000000..a42e6c4de --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-bad.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: Pod +metadata: + name: badpod01 +spec: + containers: + - name: busybox + image: k8s.gcr.io/busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod02 +spec: + initContainers: + - name: busybox-init + image: k8s.gcr.io/busybox:1.35 + - name: busybox-init-again + image: foo.gcr.io/busybox:1.35 + containers: + - name: busybox + image: busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod03 +spec: + initContainers: + - name: busybox-init + image: busybox:1.35 + - name: busybox-init-again + image: foo.gcr.io/busybox:1.35 + containers: + - name: busybox + image: k8s.gcr.io/busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod04 +spec: + initContainers: + - name: busybox-init + image: docker.io/busybox:1.35 + - name: busybox-init-again + image: busybox:1.35 + containers: + - name: busybox + image: registry.k8s.io/busybox:1.35 + - name: busybox02 + image: k8s.gcr.io/busybox:1.35 + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-good.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-good.yaml new file mode 100644 index 000000000..dc600ad10 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/pod-good.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goodpod01 + namespace: dep-registry-ns +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + name: goodpod02 + namespace: dep-registry-ns +spec: + initContainers: + - name: busybox-init + image: ghcr.io/busybox:1.35 + - name: busybox-init-again + image: registry.k8s.io/busybox:1.35 + containers: + - name: busybox + image: busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-bad.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-bad.yaml new file mode 100644 index 000000000..70bf2881d --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-bad.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: baddeployment01 + namespace: dep-registry-ns +spec: + replicas: 1 + selector: + matchLabels: + foo: bar + template: + metadata: + labels: + foo: bar + spec: + initContainers: + - name: busybox-init + image: ghcr.io/busybox:1.35 + - name: busybox-init-again + image: registry.k8s.io/busybox:1.35 + containers: + - name: busybox + image: k8s.gcr.io/busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 + namespace: dep-registry-ns +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + restartPolicy: OnFailure + initContainers: + - name: busybox-init + image: k8s.gcr.io/busybox:1.35 + - name: busybox-init-again + image: registry.k8s.io/busybox:1.35 + containers: + - name: busybox + image: busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-good.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-good.yaml new file mode 100644 index 000000000..5116f3047 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/podcontroller-good.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gooddeployment01 + namespace: dep-registry-ns +spec: + replicas: 1 + selector: + matchLabels: + foo: bar + template: + metadata: + labels: + foo: bar + spec: + initContainers: + - name: busybox-init + image: ghcr.io/busybox:1.35 + - name: busybox-init-again + image: registry.k8s.io/busybox:1.35 + containers: + - name: busybox + image: busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 + namespace: dep-registry-ns +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + restartPolicy: OnFailure + initContainers: + - name: busybox-init + image: ghcr.io/busybox:1.35 + - name: busybox-init-again + image: registry.k8s.io/busybox:1.35 + containers: + - name: busybox + image: busybox:1.35 + - name: busybox02 + image: docker.io/busybox:1.35 + diff --git a/other-cel/restrict-deprecated-registry/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-deprecated-registry/.chainsaw-test/policy-ready.yaml new file mode 100644 index 000000000..8c4f59439 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-deprecated-registry +status: + ready: true + diff --git a/other-cel/restrict-deprecated-registry/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-deprecated-registry/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8fff95200 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,22 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-deprecated-registry +policies: +- ../restrict-deprecated-registry.yaml +resources: +- resource.yaml +results: +- kind: Pod + policy: restrict-deprecated-registry + resources: + - policy-test/test-pod-bad + result: fail + rule: restrict-deprecated-registry +- kind: Pod + policy: restrict-deprecated-registry + resources: + - policy-test/test-pod-good + result: pass + rule: restrict-deprecated-registry + diff --git a/other-cel/restrict-deprecated-registry/.kyverno-test/resource.yaml b/other-cel/restrict-deprecated-registry/.kyverno-test/resource.yaml new file mode 100644 index 000000000..c7b8143a4 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/.kyverno-test/resource.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod-bad + namespace: policy-test + labels: + app: test +spec: + containers: + - name: test + image: k8s.gcr.io/google-containers/pause:3.2 + imagePullPolicy: Always + securityContext: + allowPrivilegeEscalation: false + runAsUser: 1000 + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-pod-good + namespace: policy-test + labels: + app: test +spec: + containers: + - name: test + image: registry.k8s.io/google-containers/pause:3.2 + imagePullPolicy: Always + securityContext: + allowPrivilegeEscalation: false + runAsUser: 1000 + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + diff --git a/other-cel/restrict-deprecated-registry/artifacthub-pkg.yml b/other-cel/restrict-deprecated-registry/artifacthub-pkg.yml new file mode 100644 index 000000000..9862688b9 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +name: restrict-deprecated-registry-cel +version: 1.0.0 +displayName: Restrict Deprecated Registry in CEL expressions +description: >- + Legacy k8s.gcr.io container image registry will be frozen in early April 2023 k8s.gcr.io image registry will be frozen from the 3rd of April 2023. Images for Kubernetes 1.27 will not be available in the k8s.gcr.io image registry. Please read our announcement for more details. https://kubernetes.io/blog/2023/02/06/k8s-gcr-io-freeze-announcement/ +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-deprecated-registry/restrict-deprecated-registry.yaml + ``` +keywords: + - kyverno + - Best Practices + - EKS Best Practices + - CEL Expressions +readme: | + Legacy k8s.gcr.io container image registry will be frozen in early April 2023 k8s.gcr.io image registry will be frozen from the 3rd of April 2023. Images for Kubernetes 1.27 will not be available in the k8s.gcr.io image registry. Please read our announcement for more details. https://kubernetes.io/blog/2023/02/06/k8s-gcr-io-freeze-announcement/ + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Best Practices, EKS Best Practices in CEL" + kyverno/kubernetesVersion: "1.27-1.28" + kyverno/subject: "Pod" +digest: 8973c813a1c65f2137273d66cd871bfbe53d80b30bae87685713ddc1ce96eb32 +createdAt: "2024-04-13T16:21:40Z" + diff --git a/other-cel/restrict-deprecated-registry/restrict-deprecated-registry.yaml b/other-cel/restrict-deprecated-registry/restrict-deprecated-registry.yaml new file mode 100644 index 000000000..3102410a4 --- /dev/null +++ b/other-cel/restrict-deprecated-registry/restrict-deprecated-registry.yaml @@ -0,0 +1,36 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-deprecated-registry + annotations: + policies.kyverno.io/title: Restrict Deprecated Registry in CEL expressions + policies.kyverno.io/category: Best Practices, EKS Best Practices in CEL + policies.kyverno.io/severity: high + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.27-1.28" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Legacy k8s.gcr.io container image registry will be frozen in early April 2023 + k8s.gcr.io image registry will be frozen from the 3rd of April 2023. + Images for Kubernetes 1.27 will not be available in the k8s.gcr.io image registry. + Please read our announcement for more details. + https://kubernetes.io/blog/2023/02/06/k8s-gcr-io-freeze-announcement/ +spec: + validationFailureAction: Enforce + background: true + rules: + - name: restrict-deprecated-registry + match: + any: + - resources: + kinds: + - Pod + validate: + cel: + variables: + - name: allContainers + expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" + expressions: + - expression: "variables.allContainers.all(container, !container.image.startsWith('k8s.gcr.io/'))" + message: "The \"k8s.gcr.io\" image registry is deprecated. \"registry.k8s.io\" should now be used." + diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..bc6cef1cd --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,39 @@ +# 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-escalation-verbs-roles +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-escalation-verbs-roles.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-escalation-verbs-roles + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: cr-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: cr-bad.yaml + - apply: + file: role-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: role-bad.yaml + diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml new file mode 100644 index 000000000..d9660e25b --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml @@ -0,0 +1,55 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr01 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["bind", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr02 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "list"] +- apiGroups: ["batches", "rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "escalate", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr03 +rules: +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "bind"] +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["batches", "rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr04 +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] + + \ No newline at end of file diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-good.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-good.yaml new file mode 100644 index 000000000..12697fdf8 --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/cr-good.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodcr01 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodcr02 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] + diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..a0f2c0f6a --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-escalation-verbs-roles +status: + ready: true + diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-bad.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-bad.yaml new file mode 100644 index 000000000..4bf731aef --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-bad.yaml @@ -0,0 +1,45 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: badrole01 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["bind", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: badrole02 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "list"] +- apiGroups: ["batches", "rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "escalate", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: badrole03 +rules: +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "bind"] +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["batches"] + resources: ["jobs"] + verbs: ["get", "watch", "list"] + diff --git a/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-good.yaml b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-good.yaml new file mode 100644 index 000000000..e04eb72ab --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.chainsaw-test/role-good.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: goodrole01 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io", "apps"] + resources: ["deployments", "roles"] + verbs: ["get", "watch", "list"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles"] + verbs: ["update", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: goodrole02 +rules: +- apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] + diff --git a/other-cel/restrict-escalation-verbs-roles/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-escalation-verbs-roles/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..3ff164eed --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,36 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-escalation-verbs-roles +policies: +- ../restrict-escalation-verbs-roles.yaml +resources: +- resource.yaml +results: +- kind: ClusterRole + policy: restrict-escalation-verbs-roles + resources: + - badclusterrole01 + - badclusterrole02 + result: fail + rule: escalate +- kind: Role + policy: restrict-escalation-verbs-roles + resources: + - badrole01 + result: fail + rule: escalate +- kind: ClusterRole + policy: restrict-escalation-verbs-roles + resources: + - goodclusterrole01 + - goodclusterrole02 + result: pass + rule: escalate +- kind: Role + policy: restrict-escalation-verbs-roles + resources: + - goodrole01 + result: pass + rule: escalate + diff --git a/other-cel/restrict-escalation-verbs-roles/.kyverno-test/resource.yaml b/other-cel/restrict-escalation-verbs-roles/.kyverno-test/resource.yaml new file mode 100644 index 000000000..9eff62656 --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/.kyverno-test/resource.yaml @@ -0,0 +1,129 @@ +# Source: keda-base/charts/keda/templates/10-keda-clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodclusterrole01 +rules: +- apiGroups: + - "" + resources: + - configmaps + - configmaps/status + - events + verbs: + - '*' +- apiGroups: + - "" + resources: + - external + - pods + - secrets + - services + verbs: + - get + - list + - watch +- apiGroups: + - '*' + resources: + - '*' + verbs: + - get +- apiGroups: + - '*' + resources: + - '*/scale' + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + - statefulsets + verbs: + - list + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - '*' +# Source: keda-base/charts/keda/templates/20-metrics-clusterrole.yaml +- apiGroups: + - external.metrics.k8s.io + resources: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: goodclusterrole02 # system:discovery +rules: +- nonResourceURLs: + - /api + - /api/* + - /apis + - /apis/* + - /healthz + - /livez + - /openapi + - /openapi/* + - /readyz + - /version + - /version/ + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badclusterrole01 +rules: +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + verbs: + - escalate +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badclusterrole02 +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: goodrole01 +rules: +- apiGroups: + - "" + resources: + - configmaps + - configmaps/status + - events + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: badrole01 +rules: +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - impersonate + diff --git a/other-cel/restrict-escalation-verbs-roles/artifacthub-pkg.yml b/other-cel/restrict-escalation-verbs-roles/artifacthub-pkg.yml new file mode 100644 index 000000000..613ca2550 --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-escalation-verbs-roles-cel +version: 1.0.0 +displayName: Restrict Escalation Verbs in Roles in CEL expressions +description: >- + The verbs `impersonate`, `bind`, and `escalate` may all potentially lead to privilege escalation and should be tightly controlled. This policy prevents use of these verbs in Role or ClusterRole resources. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-escalation-verbs-roles/restrict-escalation-verbs-roles.yaml + ``` +keywords: + - kyverno + - Security + - CEL Expressions +readme: | + The verbs `impersonate`, `bind`, and `escalate` may all potentially lead to privilege escalation and should be tightly controlled. This policy prevents use of these verbs in Role or ClusterRole resources. + + 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: 79d9c85060d55996f3be6bbc06321edfed00daeaca5bd24a7f4436f23a96bd73 +createdAt: "2024-04-14T15:40:58Z" + diff --git a/other-cel/restrict-escalation-verbs-roles/restrict-escalation-verbs-roles.yaml b/other-cel/restrict-escalation-verbs-roles/restrict-escalation-verbs-roles.yaml new file mode 100644 index 000000000..f91c58a51 --- /dev/null +++ b/other-cel/restrict-escalation-verbs-roles/restrict-escalation-verbs-roles.yaml @@ -0,0 +1,44 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-escalation-verbs-roles + annotations: + policies.kyverno.io/title: Restrict Escalation Verbs in Roles in CEL expressions + policies.kyverno.io/category: Security in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Role, ClusterRole, RBAC + 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/description: >- + The verbs `impersonate`, `bind`, and `escalate` may all potentially lead to + privilege escalation and should be tightly controlled. This policy prevents + use of these verbs in Role or ClusterRole resources. +spec: + validationFailureAction: Audit + background: true + rules: + - name: escalate + match: + any: + - resources: + kinds: + - Role + - ClusterRole + validate: + cel: + variables: + - name: apiGroups + expression: "['*', 'rbac.authorization.k8s.io']" + - name: resources + expression: "['*', 'clusterroles', 'roles']" + - name: verbs + expression: "['*', 'bind', 'escalate', 'impersonate']" + expressions: + - expression: >- + !object.rules.exists(rule, + rule.apiGroups.exists(apiGroup, apiGroup in variables.apiGroups) && + rule.resources.exists(resource, resource in variables.resources) && + rule.verbs.exists(verb, verb in variables.verbs)) + message: "Use of verbs `escalate`, `bind`, and `impersonate` are forbidden." + diff --git a/other-cel/restrict-ingress-classes/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-ingress-classes/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..0340a8cf3 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# 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-classes +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-ingress-classes.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-ingress-classes + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ingress-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ingress-bad.yaml + diff --git a/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-bad.yaml b/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-bad.yaml new file mode 100644 index 000000000..bbacc6aa1 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-bad.yaml @@ -0,0 +1,39 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kyverno.io/foo: bar + name: badingress01 +spec: + rules: + - host: endpoint01 + https: + paths: + - backend: + service: + name: demo-svc + port: + number: 8080 + path: / + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: "foo" + kyverno.io/foo: bar + name: badingress02 +spec: + rules: + - host: endpoint01 + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-good.yaml b/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-good.yaml new file mode 100644 index 000000000..997bb6f42 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.chainsaw-test/ingress-good.yaml @@ -0,0 +1,40 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kyverno.io/foo: bar + kubernetes.io/ingress.class: "HAProxy" + name: goodingress01 +spec: + rules: + - host: endpoint01 + https: + paths: + - backend: + service: + name: demo-svc + port: + number: 8080 + path: / + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: "nginx" + kyverno.io/foo: bar + name: goodingress02 +spec: + rules: + - host: endpoint01 + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-classes/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-ingress-classes/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..bec453ba0 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-classes +status: + ready: true + diff --git a/other-cel/restrict-ingress-classes/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-ingress-classes/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..830762887 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,22 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-ingress-classes +policies: +- ../restrict-ingress-classes.yaml +resources: +- resource.yaml +results: +- kind: Ingress + policy: restrict-ingress-classes + resources: + - default/minimal-ingress-2 + result: fail + rule: validate-ingress +- kind: Ingress + policy: restrict-ingress-classes + resources: + - default/minimal-ingress-1 + result: pass + rule: validate-ingress + diff --git a/other-cel/restrict-ingress-classes/.kyverno-test/resource.yaml b/other-cel/restrict-ingress-classes/.kyverno-test/resource.yaml new file mode 100644 index 000000000..ccb97ba46 --- /dev/null +++ b/other-cel/restrict-ingress-classes/.kyverno-test/resource.yaml @@ -0,0 +1,38 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: minimal-ingress-1 + annotations: + kubernetes.io/ingress.class: "HAProxy" + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: minimal-ingress-2 + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-classes/artifacthub-pkg.yml b/other-cel/restrict-ingress-classes/artifacthub-pkg.yml new file mode 100644 index 000000000..ce6b364d9 --- /dev/null +++ b/other-cel/restrict-ingress-classes/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-ingress-classes-cel +version: 1.0.0 +displayName: Restrict Ingress Classes in CEL expressions +description: >- + Ingress classes should only be allowed which match up to deployed Ingress controllers in the cluster. Allowing users to define classes which cannot be satisfied by a deployed Ingress controller can result in either no or undesired functionality. This policy checks Ingress resources and only allows those which define `HAProxy` or `nginx` in the respective annotation. This annotation has largely been replaced as of Kubernetes 1.18 with the IngressClass resource. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-ingress-classes/restrict-ingress-classes.yaml + ``` +keywords: + - kyverno + - Sample + - CEL Expressions +readme: | + Ingress classes should only be allowed which match up to deployed Ingress controllers in the cluster. Allowing users to define classes which cannot be satisfied by a deployed Ingress controller can result in either no or undesired functionality. This policy checks Ingress resources and only allows those which define `HAProxy` or `nginx` in the respective annotation. This annotation has largely been replaced as of Kubernetes 1.18 with the IngressClass resource. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Sample in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Ingress" +digest: 1619d89eec3ee9bf4de2f76b747b01c885af2c3b42631c3b0ff1e50a6717e9e1 +createdAt: "2024-04-14T15:43:33Z" + diff --git a/other-cel/restrict-ingress-classes/restrict-ingress-classes.yaml b/other-cel/restrict-ingress-classes/restrict-ingress-classes.yaml new file mode 100644 index 000000000..f448f323b --- /dev/null +++ b/other-cel/restrict-ingress-classes/restrict-ingress-classes.yaml @@ -0,0 +1,37 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-classes + annotations: + policies.kyverno.io/title: Restrict Ingress Classes in CEL expressions + policies.kyverno.io/category: Sample in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Ingress + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Ingress classes should only be allowed which match up to deployed Ingress controllers + in the cluster. Allowing users to define classes which cannot be satisfied by a deployed + Ingress controller can result in either no or undesired functionality. This policy checks + Ingress resources and only allows those which define `HAProxy` or `nginx` in the respective + annotation. This annotation has largely been replaced as of Kubernetes 1.18 with the IngressClass + resource. +spec: + validationFailureAction: Audit + background: true + rules: + - name: validate-ingress + match: + any: + - resources: + kinds: + - Ingress + validate: + cel: + expressions: + - expression: >- + has(object.metadata.annotations) && + 'kubernetes.io/ingress.class' in object.metadata.annotations && + object.metadata.annotations['kubernetes.io/ingress.class'] in ['HAProxy', 'nginx'] + message: "Unknown ingress class." + diff --git a/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..838fbc640 --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# 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-defaultbackend +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-ingress-defaultbackend.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-ingress-defaultbackend + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ingress-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ingress-bad.yaml + diff --git a/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-bad.yaml b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-bad.yaml new file mode 100644 index 000000000..e46888ccb --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-bad.yaml @@ -0,0 +1,22 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: badingress01 +spec: + defaultBackend: + resource: + apiGroup: k8s.example.com + kind: StorageBucket + name: static-assets +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: badingress02 +spec: + defaultBackend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-good.yaml b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-good.yaml new file mode 100644 index 000000000..e35151a01 --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/ingress-good.yaml @@ -0,0 +1,34 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: goodingress01 +spec: + rules: + - host: endpoint01 + https: + paths: + - backend: + service: + name: demo-svc + port: + number: 8080 + path: / + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: goodingress02 +spec: + rules: + - host: endpoint01 + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..0767076fa --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-defaultbackend +status: + ready: true + diff --git a/other-cel/restrict-ingress-defaultbackend/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-ingress-defaultbackend/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..7b744c929 --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,22 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-node-defaultbackend +policies: +- ../restrict-ingress-defaultbackend.yaml +resources: +- resource.yaml +results: +- kind: Ingress + policy: restrict-ingress-defaultbackend + resources: + - default/sample-app-1 + result: fail + rule: restrict-ingress-defaultbackend +- kind: Ingress + policy: restrict-ingress-defaultbackend + resources: + - default/sample-app-2 + result: pass + rule: restrict-ingress-defaultbackend + diff --git a/other-cel/restrict-ingress-defaultbackend/.kyverno-test/resource.yaml b/other-cel/restrict-ingress-defaultbackend/.kyverno-test/resource.yaml new file mode 100644 index 000000000..015bc445c --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/.kyverno-test/resource.yaml @@ -0,0 +1,63 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: sample-app-1 + namespace: default +spec: + defaultBackend: + service: + name: sample-backend + port: + number: 80 + rules: + - host: sample-frontend.example.com + http: + paths: + - backend: + service: + name: sample-frontend + port: + number: 80 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - sample-frontend.example.com + secretName: sample-frontend-tls +--- + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: sample-app-2 + namespace: default +spec: + rules: + - host: sample-backend.example.com + http: + paths: + - backend: + service: + name: sample-backend + port: + number: 80 + path: / + pathType: ImplementationSpecific + - host: sample-frontend.example.com + http: + paths: + - backend: + service: + name: sample-frontend + port: + number: 80 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - sample-backend.example.com + secretName: sample-backend-tls + - hosts: + - sample-frontend.example.com + secretName: sample-frontend-tls + diff --git a/other-cel/restrict-ingress-defaultbackend/artifacthub-pkg.yml b/other-cel/restrict-ingress-defaultbackend/artifacthub-pkg.yml new file mode 100644 index 000000000..04342b17f --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-ingress-defaultbackend-cel +version: 1.0.0 +displayName: Restrict Ingress defaultBackend in CEL expressions +description: >- + An Ingress with no rules sends all traffic to a single default backend. The defaultBackend is conventionally a configuration option of the Ingress controller and is not specified in your Ingress resources. If none of the hosts or paths match the HTTP request in the Ingress objects, the traffic is routed to your default backend. In a multi-tenant environment, you want users to use explicit hosts, they should not be able to overwrite the global default backend service. This policy prohibits the use of the defaultBackend field. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-ingress-defaultbackend/restrict-ingress-defaultbackend.yaml + ``` +keywords: + - kyverno + - Best Practices + - CEL Expressions +readme: | + An Ingress with no rules sends all traffic to a single default backend. The defaultBackend is conventionally a configuration option of the Ingress controller and is not specified in your Ingress resources. If none of the hosts or paths match the HTTP request in the Ingress objects, the traffic is routed to your default backend. In a multi-tenant environment, you want users to use explicit hosts, they should not be able to overwrite the global default backend service. This policy prohibits the use of the defaultBackend field. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Best Practices in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Ingress" +digest: daed0d8b9b07fa2d102540d7f7204752cc44ace565668469b66ac2d224c87ca4 +createdAt: "2024-04-14T15:45:57Z" + diff --git a/other-cel/restrict-ingress-defaultbackend/restrict-ingress-defaultbackend.yaml b/other-cel/restrict-ingress-defaultbackend/restrict-ingress-defaultbackend.yaml new file mode 100644 index 000000000..96bbb1fa8 --- /dev/null +++ b/other-cel/restrict-ingress-defaultbackend/restrict-ingress-defaultbackend.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-defaultbackend + annotations: + policies.kyverno.io/title: Restrict Ingress defaultBackend in CEL expressions + policies.kyverno.io/category: Best Practices 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: Ingress + policies.kyverno.io/description: >- + An Ingress with no rules sends all traffic to a single default backend. The defaultBackend + is conventionally a configuration option of the Ingress controller and is not specified in + your Ingress resources. If none of the hosts or paths match the HTTP request in the Ingress + objects, the traffic is routed to your default backend. In a multi-tenant environment, you + want users to use explicit hosts, they should not be able to overwrite the global default backend + service. This policy prohibits the use of the defaultBackend field. +spec: + validationFailureAction: Audit + background: true + rules: + - name: restrict-ingress-defaultbackend + match: + any: + - resources: + kinds: + - Ingress + validate: + cel: + expressions: + - expression: "!has(object.spec.defaultBackend)" + message: Setting the defaultBackend field is prohibited. + diff --git a/other-cel/restrict-ingress-wildcard/.chainsaw-test/chainsaw-test.yaml b/other-cel/restrict-ingress-wildcard/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..6361d5eb8 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# 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-wildcard +spec: + steps: + - name: step-01 + try: + - apply: + file: ../restrict-ingress-wildcard.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: restrict-ingress-wildcard + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ingress-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ingress-bad.yaml + diff --git a/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml b/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml new file mode 100644 index 000000000..f54f1e3bf --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml @@ -0,0 +1,71 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: badingress01 +spec: + rules: + - host: "*.foo.bar" + https: + paths: + - backend: + service: + name: demo-svc + port: + number: 8080 + path: / + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: badingress02 +spec: + rules: + - host: foo-bar + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + - host: "*.example.com" + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: badingress03 +spec: + rules: + - host: "*.bar" + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + - host: foo-bar + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-good.yaml b/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-good.yaml new file mode 100644 index 000000000..aa30b1149 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.chainsaw-test/ingress-good.yaml @@ -0,0 +1,44 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: goodingress01 +spec: + rules: + - host: endpoint01 + https: + paths: + - backend: + service: + name: demo-svc + port: + number: 8080 + path: / + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: goodingress02 +spec: + rules: + - host: endpoint02 + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + - host: endpoint01 + https: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + diff --git a/other-cel/restrict-ingress-wildcard/.chainsaw-test/policy-ready.yaml b/other-cel/restrict-ingress-wildcard/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..df65e8004 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,7 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-wildcard +status: + ready: true + diff --git a/other-cel/restrict-ingress-wildcard/.kyverno-test/kyverno-test.yaml b/other-cel/restrict-ingress-wildcard/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..c2fdee981 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,24 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-ingress-wildcard +policies: +- ../restrict-ingress-wildcard.yaml +resources: +- resources.yaml +results: +- kind: Ingress + policy: restrict-ingress-wildcard + resources: + - bading01 + - bading02 + result: fail + rule: block-ingress-wildcard +- kind: Ingress + policy: restrict-ingress-wildcard + resources: + - gooding01 + - gooding02 + result: pass + rule: block-ingress-wildcard + diff --git a/other-cel/restrict-ingress-wildcard/.kyverno-test/resources.yaml b/other-cel/restrict-ingress-wildcard/.kyverno-test/resources.yaml new file mode 100644 index 000000000..6b0616771 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/.kyverno-test/resources.yaml @@ -0,0 +1,109 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bading01 + labels: + app: kuard +spec: + rules: + - host: '*.foo.com' + http: + paths: + - backend: + service: + name: kuard + port: + number: 8080 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - kuard +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bading02 + labels: + app: kuard +spec: + rules: + - host: host1.foo.com + http: + paths: + - backend: + service: + name: kuard + port: + number: 8080 + path: / + pathType: ImplementationSpecific + - host: '*.foo.com' + http: + paths: + - backend: + service: + name: star + port: + number: 8082 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - kuard +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: gooding01 + labels: + app: kuard +spec: + rules: + - host: corp.foo.com + http: + paths: + - backend: + service: + name: kuard + port: + number: 8080 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - kuard +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: gooding02 + labels: + app: kuard +spec: + rules: + - host: corp.foo.com + http: + paths: + - backend: + service: + name: kuard + port: + number: 8080 + path: / + pathType: ImplementationSpecific + - host: bar.foo.com + http: + paths: + - backend: + service: + name: bar + port: + number: 8082 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - kuard + diff --git a/other-cel/restrict-ingress-wildcard/artifacthub-pkg.yml b/other-cel/restrict-ingress-wildcard/artifacthub-pkg.yml new file mode 100644 index 000000000..30e88d18c --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: restrict-ingress-wildcard-cel +version: 1.0.0 +displayName: Restrict Ingress Host with Wildcards in CEL expressions +description: >- + Ingress hosts optionally accept a wildcard as an alternative to precise matching. In some cases, this may be too permissive as it would direct unintended traffic to the given Ingress resource. This policy enforces that any Ingress host does not contain a wildcard character. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other-cel/restrict-ingress-wildcard/restrict-ingress-wildcard.yaml + ``` +keywords: + - kyverno + - Other + - CEL Expressions +readme: | + Ingress hosts optionally accept a wildcard as an alternative to precise matching. In some cases, this may be too permissive as it would direct unintended traffic to the given Ingress resource. This policy enforces that any Ingress host does not contain a wildcard character. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Other in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Ingress" +digest: efc9d13e01f12ada9ae55b8cd4ef572c767670d65ca189bdea4857969a3a7365 +createdAt: "2024-04-15T18:06:41Z" + diff --git a/other-cel/restrict-ingress-wildcard/restrict-ingress-wildcard.yaml b/other-cel/restrict-ingress-wildcard/restrict-ingress-wildcard.yaml new file mode 100644 index 000000000..7cc5de6a2 --- /dev/null +++ b/other-cel/restrict-ingress-wildcard/restrict-ingress-wildcard.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: restrict-ingress-wildcard + annotations: + policies.kyverno.io/title: Restrict Ingress Host with Wildcards in CEL expressions + policies.kyverno.io/category: Other 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: Ingress + policies.kyverno.io/description: >- + Ingress hosts optionally accept a wildcard as an alternative + to precise matching. In some cases, this may be too permissive as it + would direct unintended traffic to the given Ingress resource. This + policy enforces that any Ingress host does not contain a wildcard + character. +spec: + validationFailureAction: Audit + background: true + rules: + - name: block-ingress-wildcard + match: + any: + - resources: + kinds: + - Ingress + validate: + cel: + expressions: + - expression: "!has(object.spec.rules) || !object.spec.rules.exists(rule, has(rule.host) && rule.host.contains('*'))" + message: "Wildcards are not permitted as hosts." + diff --git a/other/restrict-annotations/.chainsaw-test/pod-bad.yaml b/other/restrict-annotations/.chainsaw-test/pod-bad.yaml index 442100ab4..87a6bad2d 100644 --- a/other/restrict-annotations/.chainsaw-test/pod-bad.yaml +++ b/other/restrict-annotations/.chainsaw-test/pod-bad.yaml @@ -3,7 +3,7 @@ kind: Pod metadata: annotations: fluxcd.io/foo: bar - name: goodpod01 + name: badpod01 spec: containers: - name: busybox @@ -16,7 +16,7 @@ metadata: bar: foo fluxcd.io/foo: bar foo: bar - name: goodpod02 + name: badpod02 spec: containers: - name: busybox @@ -27,9 +27,9 @@ kind: Pod metadata: annotations: bar: foo - fluxcd.io/: bar + fluxcd.io/hello: bar foo: bar - name: goodpod02 + name: badpod03 spec: containers: - name: busybox diff --git a/other/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml b/other/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8b2670ad9 --- /dev/null +++ b/other/restrict-binding-clusteradmin/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,41 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-binding-clusteradmin +policies: +- ../restrict-binding-clusteradmin.yaml +resources: +- ../.chainsaw-test/crb-bad.yaml +- ../.chainsaw-test/crb-good.yaml +- ../.chainsaw-test/rb-bad.yaml +- ../.chainsaw-test/rb-good.yaml +results: +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: ClusterRoleBinding + resources: + - badcrb01 + - badcrb02 + result: fail +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + result: pass +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: RoleBinding + resources: + - badrb01 + - badrb02 + result: fail +- policy: restrict-binding-clusteradmin + rule: clusteradmin-bindings + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + result: pass + diff --git a/other/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml b/other/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml index 64f050807..2186c4010 100644 --- a/other/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml +++ b/other/restrict-binding-system-groups/.chainsaw-test/crb-bad.yaml @@ -16,7 +16,7 @@ kind: ClusterRoleBinding metadata: name: badcrb02 subjects: -- kind: ServiceAccount +- kind: Group namespace: foo name: "system:unauthenticated" apiGroup: rbac.authorization.k8s.io diff --git a/other/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml b/other/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..df411658c --- /dev/null +++ b/other/restrict-binding-system-groups/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,96 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-binding-system-groups +policies: +- ../restrict-binding-system-groups.yaml +resources: +- ../.chainsaw-test/crb-bad.yaml +- ../.chainsaw-test/crb-good.yaml +- ../.chainsaw-test/rb-bad.yaml +- ../.chainsaw-test/rb-good.yaml +results: +- policy: restrict-binding-system-groups + rule: restrict-anonymous + kind: ClusterRoleBinding + resources: + - badcrb01 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-unauthenticated + kind: ClusterRoleBinding + resources: + - badcrb02 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-masters + kind: ClusterRoleBinding + resources: + - badcrb03 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-anonymous + kind: RoleBinding + resources: + - badrb01 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-unauthenticated + kind: RoleBinding + resources: + - badrb02 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-masters + kind: RoleBinding + resources: + - badrb03 + result: fail +- policy: restrict-binding-system-groups + rule: restrict-anonymous + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + - goodcrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-unauthenticated + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + - goodcrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-masters + kind: ClusterRoleBinding + resources: + - goodcrb01 + - goodcrb02 + - goodcrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-anonymous + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + - goodrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-unauthenticated + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + - goodrb03 + result: pass +- policy: restrict-binding-system-groups + rule: restrict-masters + kind: RoleBinding + resources: + - goodrb01 + - goodrb02 + - goodrb03 + result: pass diff --git a/other/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml b/other/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..9a119fe0d --- /dev/null +++ b/other/restrict-clusterrole-nodesproxy/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,25 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: restrict-clusterrole-nodesproxy +policies: +- ../restrict-clusterrole-nodesproxy.yaml +resources: +- ../.chainsaw-test/cr-bad.yaml +- ../.chainsaw-test/cr-good.yaml +results: +- policy: restrict-clusterrole-nodesproxy + rule: clusterrole-nodesproxy + kind: ClusterRole + resources: + - badcr01 + - badcr02 + result: fail +- policy: restrict-clusterrole-nodesproxy + rule: clusterrole-nodesproxy + kind: ClusterRole + resources: + - goodcr01 + - goodcr02 + result: pass + diff --git a/other/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml b/other/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml index be57eb271..5832aee34 100644 --- a/other/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml +++ b/other/restrict-escalation-verbs-roles/.chainsaw-test/cr-bad.yaml @@ -41,4 +41,14 @@ rules: verbs: ["get", "watch", "list"] - apiGroups: ["batches", "rbac.authorization.k8s.io"] resources: ["clusterroles"] - verbs: ["get", "watch", "list"] \ No newline at end of file + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: badcr04 +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] + diff --git a/other/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml b/other/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml index bfa869489..b6bce89c8 100644 --- a/other/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml +++ b/other/restrict-ingress-wildcard/.chainsaw-test/ingress-bad.yaml @@ -31,7 +31,7 @@ spec: name: test port: number: 80 - - host: "foo.*.com" + - host: "*.example.com" https: paths: - path: /testpath