diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac52631ac..b4ce3c5e2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,9 +44,12 @@ jobs: - ^flux$ - ^flux-cel$ - ^istio$ + - ^istio-cel$ - ^karpenter$ - ^kasten$ + - ^kasten-cel$ - ^kubecost$ + - ^kubecost-cel$ - ^kubeops$ - ^kubevirt$ - ^linkerd$ diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/chainsaw-test.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..c160abb64 --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,41 @@ +# 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: enforce-sidecar-injection-namespace +spec: + steps: + - name: step-01 + try: + - apply: + file: ../enforce-sidecar-injection-namespace.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: enforce-sidecar-injection-namespace + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: ns-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ns-bad-disabled.yaml + - apply: + expect: + - check: + ($error != null): true + file: ns-bad-nolabel.yaml + - apply: + expect: + - check: + ($error != null): true + file: ns-bad-somelabel.yaml diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-disabled.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-disabled.yaml new file mode 100644 index 000000000..0eec7ea44 --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-disabled.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + istio-injection: disabled + name: bad-istio-sinj01 \ No newline at end of file diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-nolabel.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-nolabel.yaml new file mode 100644 index 000000000..4caa0efdb --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-nolabel.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: bad-istio-sinj03 \ No newline at end of file diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-somelabel.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-somelabel.yaml new file mode 100644 index 000000000..d25585d2a --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-bad-somelabel.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + foo: enabled + name: bad-istio-sinj02 \ No newline at end of file diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-good.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-good.yaml new file mode 100644 index 000000000..a5f30d2ac --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/ns-good.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + istio-injection: enabled + name: good-istio-sinj01 +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + foo: disabled + istio-injection: enabled + bar: enabled + name: good-istio-sinj02 \ No newline at end of file diff --git a/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/policy-ready.yaml b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..acc3f29fb --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: enforce-sidecar-injection-namespace +status: + ready: true diff --git a/istio-cel/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml b/istio-cel/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..e457fa2b8 --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,28 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: enforce-sidecar-injection-namespace +policies: +- ../enforce-sidecar-injection-namespace.yaml +resources: +- ../.chainsaw-test/ns-bad-disabled.yaml +- ../.chainsaw-test/ns-bad-nolabel.yaml +- ../.chainsaw-test/ns-bad-somelabel.yaml +- ../.chainsaw-test/ns-good.yaml +results: +- policy: enforce-sidecar-injection-namespace + rule: check-istio-injection-enabled + kind: Namespace + resources: + - bad-istio-sinj01 + - bad-istio-sinj02 + - bad-istio-sinj03 + result: fail +- policy: enforce-sidecar-injection-namespace + rule: check-istio-injection-enabled + kind: Namespace + resources: + - good-istio-sinj01 + - good-istio-sinj02 + result: pass + diff --git a/istio-cel/enforce-sidecar-injection-namespace/artifacthub-pkg.yml b/istio-cel/enforce-sidecar-injection-namespace/artifacthub-pkg.yml new file mode 100644 index 000000000..177e3d150 --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: enforce-sidecar-injection-namespace-cel +version: 1.0.0 +displayName: Enforce Istio Sidecar Injection in CEL expressions +description: >- + In order for Istio to inject sidecars to workloads deployed into Namespaces, the label `istio-injection` must be set to `enabled`. This policy ensures that all new Namespaces set `istio-inject` to `enabled`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/istio-cel/enforce-sidecar-injection-namespace/enforce-sidecar-injection-namespace.yaml + ``` +keywords: + - kyverno + - Istio + - CEL Expressions +readme: | + In order for Istio to inject sidecars to workloads deployed into Namespaces, the label `istio-injection` must be set to `enabled`. This policy ensures that all new Namespaces set `istio-inject` to `enabled`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Istio in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Namespace" +digest: 123feb2a8d1b2743e33b1f91ddf7291c47eedcf2c24ae537a1d3afe6c503338d +createdAt: "2024-05-12T04:38:32Z" + diff --git a/istio-cel/enforce-sidecar-injection-namespace/enforce-sidecar-injection-namespace.yaml b/istio-cel/enforce-sidecar-injection-namespace/enforce-sidecar-injection-namespace.yaml new file mode 100644 index 000000000..5a2c91d80 --- /dev/null +++ b/istio-cel/enforce-sidecar-injection-namespace/enforce-sidecar-injection-namespace.yaml @@ -0,0 +1,34 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: enforce-sidecar-injection-namespace + annotations: + policies.kyverno.io/title: Enforce Istio Sidecar Injection in CEL expressions + policies.kyverno.io/category: Istio in CEL + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/subject: Namespace + policies.kyverno.io/description: >- + In order for Istio to inject sidecars to workloads deployed into Namespaces, the label + `istio-injection` must be set to `enabled`. This policy ensures that all new Namespaces + set `istio-inject` to `enabled`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: check-istio-injection-enabled + match: + any: + - resources: + kinds: + - Namespace + operations: + - CREATE + validate: + cel: + expressions: + - expression: "has(object.metadata.labels) && 'istio-injection' in object.metadata.labels && object.metadata.labels['istio-injection'] == 'enabled'" + message: "All new Namespaces must have Istio sidecar injection enabled." + diff --git a/istio-cel/enforce-strict-mtls/.chainsaw-test/chainsaw-test.yaml b/istio-cel/enforce-strict-mtls/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..e547cafa5 --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,33 @@ +# 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: enforce-strict-mtls +spec: + steps: + - name: step-01 + try: + - apply: + file: ../enforce-strict-mtls.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: enforce-strict-mtls + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - assert: + file: crd-assert.yaml + - name: step-02 + try: + - apply: + file: pa-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pa-bad.yaml diff --git a/istio-cel/enforce-strict-mtls/.chainsaw-test/crd-assert.yaml b/istio-cel/enforce-strict-mtls/.chainsaw-test/crd-assert.yaml new file mode 100755 index 000000000..56561a629 --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.chainsaw-test/crd-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: peerauthentications.security.istio.io +spec: {} +status: + acceptedNames: + kind: PeerAuthentication + listKind: PeerAuthenticationList + plural: peerauthentications + singular: peerauthentication + storedVersions: + - v1beta1 diff --git a/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-bad.yaml b/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-bad.yaml new file mode 100644 index 000000000..771d21f3d --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-bad.yaml @@ -0,0 +1,26 @@ +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: pa-bad01 +spec: + mtls: + mode: PERMISSIVE +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: pa-bad02 +spec: + mtls: + mode: DISABLE +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: pa-bad03 +spec: + selector: + matchLabels: + app: finance + mtls: + mode: DISABLE \ No newline at end of file diff --git a/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-good.yaml b/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-good.yaml new file mode 100644 index 000000000..0d2d9d383 --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.chainsaw-test/pa-good.yaml @@ -0,0 +1,39 @@ +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: good-pa01 +spec: + mtls: + mode: STRICT +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: good-pa02 +spec: + mtls: + mode: UNSET +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: good-pa03 +spec: {} +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: good-pa04 +spec: + selector: + matchLabels: + app: finance + mtls: + mode: STRICT +--- +apiVersion: security.istio.io/v1beta1 +kind: PeerAuthentication +metadata: + name: good-pa05 +spec: + mtls: {} \ No newline at end of file diff --git a/istio-cel/enforce-strict-mtls/.chainsaw-test/policy-ready.yaml b/istio-cel/enforce-strict-mtls/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..c5f7637cb --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: enforce-strict-mtls +status: + ready: true diff --git a/istio-cel/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml b/istio-cel/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..f4018437a --- /dev/null +++ b/istio-cel/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,29 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: enforce-strict-mtls +policies: +- ../enforce-strict-mtls.yaml +resources: +- ../.chainsaw-test/pa-bad.yaml +- ../.chainsaw-test/pa-good.yaml +results: +- policy: enforce-strict-mtls + rule: validate-mtls + kind: PeerAuthentication + resources: + - pa-bad01 + - pa-bad02 + - pa-bad03 + result: fail +- policy: enforce-strict-mtls + rule: validate-mtls + kind: PeerAuthentication + resources: + - good-pa01 + - good-pa02 + - good-pa03 + - good-pa04 + - good-pa05 + result: pass + diff --git a/istio-cel/enforce-strict-mtls/artifacthub-pkg.yml b/istio-cel/enforce-strict-mtls/artifacthub-pkg.yml new file mode 100644 index 000000000..e760f1c9e --- /dev/null +++ b/istio-cel/enforce-strict-mtls/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: enforce-strict-mtls-cel +version: 1.0.0 +displayName: Enforce Istio Strict mTLS in CEL expressions +description: >- + Strict mTLS requires that mutual TLS be enabled across the entire service mesh, which can be set using a PeerAuthentication resource on a per-Namespace basis and, if set on the `istio-system` Namespace could disable it across the entire mesh. Disabling mTLS can reduce the security for traffic within that portion of the mesh and should be controlled. This policy prevents disabling strict mTLS in a PeerAuthentication resource by requiring the `mode` be set to either `UNSET` or `STRICT`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/istio-cel/enforce-strict-mtls/enforce-strict-mtls.yaml + ``` +keywords: + - kyverno + - Istio + - CEL Expressions +readme: | + Strict mTLS requires that mutual TLS be enabled across the entire service mesh, which can be set using a PeerAuthentication resource on a per-Namespace basis and, if set on the `istio-system` Namespace could disable it across the entire mesh. Disabling mTLS can reduce the security for traffic within that portion of the mesh and should be controlled. This policy prevents disabling strict mTLS in a PeerAuthentication resource by requiring the `mode` be set to either `UNSET` or `STRICT`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Istio in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "PeerAuthentication" +digest: 6bf5af52d9187ac5b1b90879ab3975ea618b38d04928ceecd4779fc2b2e4b26a +createdAt: "2024-05-12T04:41:47Z" + diff --git a/istio-cel/enforce-strict-mtls/enforce-strict-mtls.yaml b/istio-cel/enforce-strict-mtls/enforce-strict-mtls.yaml new file mode 100644 index 000000000..33747bbfd --- /dev/null +++ b/istio-cel/enforce-strict-mtls/enforce-strict-mtls.yaml @@ -0,0 +1,40 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: enforce-strict-mtls + annotations: + policies.kyverno.io/title: Enforce Istio Strict mTLS in CEL expressions + policies.kyverno.io/category: Istio in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: PeerAuthentication + 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: >- + Strict mTLS requires that mutual TLS be enabled across the entire service mesh, which + can be set using a PeerAuthentication resource on a per-Namespace basis and, if set on + the `istio-system` Namespace could disable it across the entire mesh. Disabling mTLS + can reduce the security for traffic within that portion of the mesh and should be controlled. + This policy prevents disabling strict mTLS in a PeerAuthentication resource by requiring + the `mode` be set to either `UNSET` or `STRICT`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: validate-mtls + match: + any: + - resources: + kinds: + - PeerAuthentication + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + !has(object.spec) || !has(object.spec.mtls) || !has(object.spec.mtls.mode) || + object.spec.mtls.mode in ['UNSET', 'STRICT'] + message: "PeerAuthentication resources may only set UNSET or STRICT for the mode." + diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/chainsaw-test.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..a1695faa6 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: prevent-disabling-injection-pods +spec: + steps: + - name: step-01 + try: + - apply: + file: ../prevent-disabling-injection-pods.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: prevent-disabling-injection-pods + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod-good.yaml + - apply: + file: podcontroller-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pod-bad.yaml + - apply: + expect: + - check: + ($error != null): true + file: podcontroller-bad.yaml diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml new file mode 100644 index 000000000..3f2e6b492 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + annotations: + app.k8s.io/name: badpod01 + sidecar.istio.io/inject: "false" + name: badpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + annotations: + sidecar.istio.io/inject: "false" + app.k8s.io/name: badpod02 + name: badpod02 +spec: + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-good.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-good.yaml new file mode 100644 index 000000000..de1e03c32 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/pod-good.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + annotations: + app.k8s.io/name: goodpod01 + sidecar.istio.io/inject: "true" + name: goodpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + annotations: + app.k8s.io/name: goodpod02 + name: goodpod02 +spec: + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml new file mode 100644 index 000000000..90c90ffc0 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml @@ -0,0 +1,89 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + app.k8s.io/name: busybox + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + annotations: + app.k8s.io/name: busybox + sidecar.istio.io/inject: "false" + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + app.k8s.io/name: busybox + sidecar.istio.io/inject: "false" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - sleep + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + app.k8s.io/name: busybox + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - sleep + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml new file mode 100644 index 000000000..59d1afa1b --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml @@ -0,0 +1,87 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + annotations: + app.k8s.io/name: busybox + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + annotations: + app.k8s.io/name: busybox + sidecar.istio.io/inject: "true" + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + app.k8s.io/name: busybox + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + annotations: + app.k8s.io/name: busybox + sidecar.istio.io/inject: "true" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/policy-ready.yaml b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..4c6866bd0 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-disabling-injection-pods +status: + ready: true diff --git a/istio-cel/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml b/istio-cel/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..5aa5be9ad --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,55 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-disabling-injection-pods +policies: +- ../prevent-disabling-injection-pods.yaml +resources: +- ../.chainsaw-test/pod-bad.yaml +- ../.chainsaw-test/podcontroller-bad.yaml +- ../.chainsaw-test/pod-good.yaml +- ../.chainsaw-test/podcontroller-good.yaml +results: +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Pod + resources: + - badpod01 + - badpod02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Deployment + resources: + - baddeploy01 + - baddeploy02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: CronJob + resources: + - badcronjob01 + - badcronjob02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass + diff --git a/istio-cel/prevent-disabling-injection-pods/artifacthub-pkg.yml b/istio-cel/prevent-disabling-injection-pods/artifacthub-pkg.yml new file mode 100644 index 000000000..36ec09a25 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: prevent-disabling-injection-pods-cel +version: 1.0.0 +displayName: Prevent Disabling Istio Sidecar Injection in CEL expressions +description: >- + One way sidecar injection in an Istio service mesh may be accomplished is by defining an annotation at the Pod level. Pods not receiving a sidecar cannot participate in the mesh thereby reducing visibility. This policy ensures that Pods cannot set the annotation `sidecar.istio.io/inject` to a value of `false`. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/istio-cel/prevent-disabling-injection-pods/prevent-disabling-injection-pods.yaml + ``` +keywords: + - kyverno + - Istio + - CEL Expressions +readme: | + One way sidecar injection in an Istio service mesh may be accomplished is by defining an annotation at the Pod level. Pods not receiving a sidecar cannot participate in the mesh thereby reducing visibility. This policy ensures that Pods cannot set the annotation `sidecar.istio.io/inject` to a value of `false`. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Istio in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod" +digest: 5de03c078273ce913a6ebf9064a85be4255b82e36f74bda822984e261363fe8b +createdAt: "2024-05-12T04:48:58Z" + diff --git a/istio-cel/prevent-disabling-injection-pods/prevent-disabling-injection-pods.yaml b/istio-cel/prevent-disabling-injection-pods/prevent-disabling-injection-pods.yaml new file mode 100644 index 000000000..6662e5151 --- /dev/null +++ b/istio-cel/prevent-disabling-injection-pods/prevent-disabling-injection-pods.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: prevent-disabling-injection-pods + annotations: + policies.kyverno.io/title: Prevent Disabling Istio Sidecar Injection in CEL expressions + policies.kyverno.io/category: Istio 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: Pod + policies.kyverno.io/description: >- + One way sidecar injection in an Istio service mesh may be accomplished is by defining + an annotation at the Pod level. Pods not receiving a sidecar cannot participate in the mesh + thereby reducing visibility. This policy ensures that Pods cannot set the annotation + `sidecar.istio.io/inject` to a value of `false`. +spec: + validationFailureAction: Audit + background: true + rules: + - name: prohibit-inject-annotation + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + !has(object.metadata.annotations) || !('sidecar.istio.io/inject' in object.metadata.annotations) || + object.metadata.annotations['sidecar.istio.io/inject'] != 'false' + message: "Pods may not disable sidecar injection by setting the annotation sidecar.istio.io/inject to a value of false." + diff --git a/istio/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml b/istio/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..e457fa2b8 --- /dev/null +++ b/istio/enforce-sidecar-injection-namespace/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,28 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: enforce-sidecar-injection-namespace +policies: +- ../enforce-sidecar-injection-namespace.yaml +resources: +- ../.chainsaw-test/ns-bad-disabled.yaml +- ../.chainsaw-test/ns-bad-nolabel.yaml +- ../.chainsaw-test/ns-bad-somelabel.yaml +- ../.chainsaw-test/ns-good.yaml +results: +- policy: enforce-sidecar-injection-namespace + rule: check-istio-injection-enabled + kind: Namespace + resources: + - bad-istio-sinj01 + - bad-istio-sinj02 + - bad-istio-sinj03 + result: fail +- policy: enforce-sidecar-injection-namespace + rule: check-istio-injection-enabled + kind: Namespace + resources: + - good-istio-sinj01 + - good-istio-sinj02 + result: pass + diff --git a/istio/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml b/istio/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..f4018437a --- /dev/null +++ b/istio/enforce-strict-mtls/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,29 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: enforce-strict-mtls +policies: +- ../enforce-strict-mtls.yaml +resources: +- ../.chainsaw-test/pa-bad.yaml +- ../.chainsaw-test/pa-good.yaml +results: +- policy: enforce-strict-mtls + rule: validate-mtls + kind: PeerAuthentication + resources: + - pa-bad01 + - pa-bad02 + - pa-bad03 + result: fail +- policy: enforce-strict-mtls + rule: validate-mtls + kind: PeerAuthentication + resources: + - good-pa01 + - good-pa02 + - good-pa03 + - good-pa04 + - good-pa05 + result: pass + diff --git a/istio/enforce-tls-hosts-host-subnets/.kyverno-test/kyverno-test.yaml b/istio/enforce-tls-hosts-host-subnets/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..8b2e1cf9b --- /dev/null +++ b/istio/enforce-tls-hosts-host-subnets/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,28 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: enforce-tls-hosts-host-subnets +policies: +- ../enforce-tls-hosts-host-subnets.yaml +resources: +- ../.chainsaw-test/dr-bad.yaml +- ../.chainsaw-test/dr-good.yaml +results: +- policy: enforce-tls-hosts-host-subnets + rule: destrule + kind: DestinationRule + resources: + - bad-dr01 + - bad-dr02 + result: fail +- policy: enforce-tls-hosts-host-subnets + rule: destrule + kind: DestinationRule + resources: + - good-dr01 + - good-dr02 + - good-dr03 + - good-dr04 + - good-dr05 + result: pass + diff --git a/istio/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml b/istio/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml index d68283137..3f2e6b492 100644 --- a/istio/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml +++ b/istio/prevent-disabling-injection-pods/.chainsaw-test/pod-bad.yaml @@ -19,8 +19,8 @@ metadata: foo: bar annotations: sidecar.istio.io/inject: "false" - app.k8s.io/name: badpod01 - name: badpod01 + app.k8s.io/name: badpod02 + name: badpod02 spec: containers: - name: busybox diff --git a/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml b/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml index ad858a2d7..90c90ffc0 100644 --- a/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml +++ b/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-bad.yaml @@ -53,16 +53,17 @@ spec: jobTemplate: spec: template: - spec: + metadata: annotations: app.k8s.io/name: busybox sidecar.istio.io/inject: "false" + spec: containers: - name: hello image: busybox:1.35 command: - sleep - - 3600 + - "3600" restartPolicy: OnFailure --- apiVersion: batch/v1 @@ -74,14 +75,15 @@ spec: jobTemplate: spec: template: - spec: + metadata: annotations: sidecar.istio.io/inject: "false" app.k8s.io/name: busybox + spec: containers: - name: hello image: busybox:1.35 - command: + command: - sleep - - 3600 + - "3600" restartPolicy: OnFailure \ No newline at end of file diff --git a/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml b/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml index 387a650ab..59d1afa1b 100644 --- a/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml +++ b/istio/prevent-disabling-injection-pods/.chainsaw-test/podcontroller-good.yaml @@ -52,9 +52,10 @@ spec: jobTemplate: spec: template: - spec: + metadata: annotations: app.k8s.io/name: busybox + spec: containers: - name: hello image: busybox:1.35 @@ -72,10 +73,11 @@ spec: jobTemplate: spec: template: - spec: + metadata: annotations: app.k8s.io/name: busybox sidecar.istio.io/inject: "true" + spec: containers: - name: hello image: busybox:1.35 diff --git a/istio/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml b/istio/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..5aa5be9ad --- /dev/null +++ b/istio/prevent-disabling-injection-pods/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,55 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: prevent-disabling-injection-pods +policies: +- ../prevent-disabling-injection-pods.yaml +resources: +- ../.chainsaw-test/pod-bad.yaml +- ../.chainsaw-test/podcontroller-bad.yaml +- ../.chainsaw-test/pod-good.yaml +- ../.chainsaw-test/podcontroller-good.yaml +results: +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Pod + resources: + - badpod01 + - badpod02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Deployment + resources: + - baddeploy01 + - baddeploy02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: CronJob + resources: + - badcronjob01 + - badcronjob02 + result: fail +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Pod + resources: + - goodpod01 + - goodpod02 + result: pass +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: Deployment + resources: + - gooddeploy01 + - gooddeploy02 + result: pass +- policy: prevent-disabling-injection-pods + rule: prohibit-inject-annotation + kind: CronJob + resources: + - goodcronjob01 + - goodcronjob02 + result: pass + diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/chainsaw-test.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..81d089924 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,60 @@ +# 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: k10-data-protection-by-label +spec: + steps: + - name: step-01 + try: + - apply: + file: ../k10-data-protection-by-label.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: k10-data-protection-by-label + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - assert: + file: crd-assert.yaml + - name: step-02 + try: + - apply: + file: ns.yaml + - apply: + file: deployment-good.yaml + - apply: + file: ss-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: deployment-bad-badlabel.yaml + - apply: + expect: + - check: + ($error != null): true + file: deployment-bad-nolabel.yaml + - apply: + expect: + - check: + ($error != null): true + file: ss-bad-badlabel.yaml + - apply: + expect: + - check: + ($error != null): true + file: ss-bad-nolabel.yaml + - name: step-98 + try: + - script: + content: kubectl delete deployments --all --force --grace-period=0 -n k10-dplabel-ns + - script: + content: kubectl delete statefulsets --all --force --grace-period=0 -n k10-dplabel-ns + - script: + content: kubectl delete pods --all --force --grace-period=0 -n k10-dplabel-ns diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/crd-assert.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/crd-assert.yaml new file mode 100755 index 000000000..d660e00cb --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/crd-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: policies.config.kio.kasten.io +spec: {} +status: + acceptedNames: + kind: Policy + listKind: PolicyList + plural: policies + singular: policy + storedVersions: + - v1alpha1 diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-badlabel.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-badlabel.yaml new file mode 100644 index 000000000..040ccdb48 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-badlabel.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: baddeploy02 + labels: + app: busybox + purpose: production + dataprotection: foo-bar +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 + command: + - "sleep" + - "3600" \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-nolabel.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-nolabel.yaml new file mode 100644 index 000000000..c34fd4785 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-bad-nolabel.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: baddeploy01 + labels: + app: busybox + purpose: production +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 + command: + - "sleep" + - "3600" \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-good.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-good.yaml new file mode 100644 index 000000000..dcf3c489e --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/deployment-good.yaml @@ -0,0 +1,75 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gooddeploy01 + namespace: k10-dplabel-ns + labels: + app: busybox + purpose: production + dataprotection: k10-goldpolicy +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 + command: + - "sleep" + - "3600" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gooddeploy02 + namespace: k10-dplabel-ns + labels: + app: busybox + purpose: development + dataprotection: foo-bar +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 + command: + - "sleep" + - "3600" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gooddeploy03 + namespace: k10-dplabel-ns + labels: + app: busybox +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 + command: + - "sleep" + - "3600" \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/nginx-deployment-invalid.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/nginx-deployment-invalid.yaml new file mode 100644 index 000000000..566318b81 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/nginx-deployment-invalid.yaml @@ -0,0 +1,31 @@ +kind: Namespace +apiVersion: v1 +metadata: + name: nginx + labels: + name: nginx +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + namespace: nginx + labels: + app: nginx + purpose: production + dataprotection: none # invalid named K10 Policy!! +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ns.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ns.yaml new file mode 100644 index 000000000..00e9c20e7 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ns.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: k10-dplabel-ns \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/policy-ready.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..4e8dfe8c2 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-data-protection-by-label +status: + ready: true diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-badlabel.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-badlabel.yaml new file mode 100644 index 000000000..cf1a15841 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-badlabel.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: bad-ss02 + labels: + purpose: production + dataprotection: foo-bar +spec: + selector: + matchLabels: + app: busybox + serviceName: busybox-ss + replicas: 1 + minReadySeconds: 10 + template: + metadata: + labels: + app: busybox + spec: + terminationGracePeriodSeconds: 10 + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-nolabel.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-nolabel.yaml new file mode 100644 index 000000000..397a81231 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-bad-nolabel.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: bad-ss01 + labels: + purpose: production +spec: + selector: + matchLabels: + app: busybox + serviceName: busybox-ss + replicas: 1 + minReadySeconds: 10 + template: + metadata: + labels: + app: busybox + spec: + terminationGracePeriodSeconds: 10 + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-good.yaml b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-good.yaml new file mode 100644 index 000000000..bc6216c38 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.chainsaw-test/ss-good.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: good-ss01 + namespace: k10-dplabel-ns + labels: + purpose: production + dataprotection: k10-silverpolicy +spec: + selector: + matchLabels: + app: busybox + serviceName: busybox-ss + replicas: 1 + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: good-ss02 + namespace: k10-dplabel-ns +spec: + selector: + matchLabels: + app: busybox + serviceName: busybox-ss + replicas: 1 + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: good-ss02 + namespace: k10-dplabel-ns + labels: + purpose: development + dataprotection: foo-bar +spec: + selector: + matchLabels: + app: busybox + serviceName: busybox-ss + replicas: 1 + template: + metadata: + labels: + app: busybox + spec: + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/kasten-cel/k10-data-protection-by-label/.kyverno-test/kyverno-test.yaml b/kasten-cel/k10-data-protection-by-label/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..58f925a36 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,21 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: kyverno_data_protection_tests +policies: +- ../k10-data-protection-by-label.yaml +resources: +- nginx-deployment.yaml +results: +- kind: Deployment + policy: k10-data-protection-by-label + resources: + - nginx-deployment-invalid + result: fail + rule: k10-data-protection-by-label +- kind: Deployment + policy: k10-data-protection-by-label + resources: + - nginx-deployment + result: pass + rule: k10-data-protection-by-label diff --git a/kasten-cel/k10-data-protection-by-label/.kyverno-test/nginx-deployment.yaml b/kasten-cel/k10-data-protection-by-label/.kyverno-test/nginx-deployment.yaml new file mode 100644 index 000000000..9ceb00a66 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/.kyverno-test/nginx-deployment.yaml @@ -0,0 +1,60 @@ +kind: Namespace +apiVersion: v1 +metadata: + name: nginx + labels: + name: nginx + purpose: production + dataprotection: k10-goldpolicy + immutable: enabled +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + namespace: nginx + labels: + app: nginx + purpose: production + dataprotection: k10-goldpolicy # set a policy to use our 'gold' standard data protection policy (generate-gold-backup-policy) + immutable: enabled +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-invalid + namespace: nginx + labels: + app: nginx + purpose: production + dataprotection: none # invalid named K10 Policy!! +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/kasten-cel/k10-data-protection-by-label/artifacthub-pkg.yml b/kasten-cel/k10-data-protection-by-label/artifacthub-pkg.yml new file mode 100644 index 000000000..2ca7fa978 --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: k10-data-protection-by-label-cel +version: 1.0.0 +displayName: Check Data Protection By Label in CEL expressions +description: >- + Check the 'dataprotection' label that production Deployments and StatefulSet have a named K10 Policy. Use in combination with 'generate' ClusterPolicy to 'generate' a specific K10 Policy by name. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/kasten-cel/k10-data-protection-by-label/k10-data-protection-by-label.yaml + ``` +keywords: + - kyverno + - Kasten K10 by Veeam + - CEL Expressions +readme: | + Check the 'dataprotection' label that production Deployments and StatefulSet have a named K10 Policy. Use in combination with 'generate' ClusterPolicy to 'generate' a specific K10 Policy by name. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Kasten K10 by Veeam in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Deployment, StatefulSet" +digest: e3a088a52aac74e16f9b2776df78891344edd6dc03ee6456dc71d71c34519325 +createdAt: "2024-05-12T07:05:48Z" + diff --git a/kasten-cel/k10-data-protection-by-label/k10-data-protection-by-label.yaml b/kasten-cel/k10-data-protection-by-label/k10-data-protection-by-label.yaml new file mode 100644 index 000000000..58270490c --- /dev/null +++ b/kasten-cel/k10-data-protection-by-label/k10-data-protection-by-label.yaml @@ -0,0 +1,36 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-data-protection-by-label + annotations: + policies.kyverno.io/title: Check Data Protection By Label in CEL expressions + policies.kyverno.io/category: Kasten K10 by Veeam in CEL + 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: Deployment, StatefulSet + policies.kyverno.io/description: >- + Check the 'dataprotection' label that production Deployments and StatefulSet have a named K10 Policy. + Use in combination with 'generate' ClusterPolicy to 'generate' a specific K10 Policy by name. +spec: + validationFailureAction: Audit + rules: + - name: k10-data-protection-by-label + match: + any: + - resources: + kinds: + - Deployment + - StatefulSet + operations: + - CREATE + - UPDATE + selector: + matchLabels: + purpose: production + validate: + cel: + expressions: + - expression: "has(object.metadata.labels) && has(object.metadata.labels.dataprotection) && object.metadata.labels.dataprotection.startsWith('k10-')" + message: "Deployments and StatefulSets that specify 'dataprotection' label must have a valid k10-?* name (use labels: dataprotection: k10-)" + diff --git a/kasten-cel/k10-hourly-rpo/.chainsaw-test/chainsaw-test.yaml b/kasten-cel/k10-hourly-rpo/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..e02442dae --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,33 @@ +# 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: k10-hourly-rpo +spec: + steps: + - name: step-01 + try: + - apply: + file: ../k10-hourly-rpo.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: k10-policy-hourly-rpo + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - assert: + file: crd-assert.yaml + - name: step-02 + try: + - apply: + file: k10-good-policy.yaml + - apply: + expect: + - check: + ($error != null): true + file: k10-bad-policy.yaml diff --git a/kasten-cel/k10-hourly-rpo/.chainsaw-test/crd-assert.yaml b/kasten-cel/k10-hourly-rpo/.chainsaw-test/crd-assert.yaml new file mode 100755 index 000000000..d660e00cb --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.chainsaw-test/crd-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: policies.config.kio.kasten.io +spec: {} +status: + acceptedNames: + kind: Policy + listKind: PolicyList + plural: policies + singular: policy + storedVersions: + - v1alpha1 diff --git a/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-bad-policy.yaml b/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-bad-policy.yaml new file mode 100644 index 000000000..1bc2dd2d6 --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-bad-policy.yaml @@ -0,0 +1,34 @@ +apiVersion: config.kio.kasten.io/v1alpha1 +kind: Policy +metadata: + name: k10-hourlyrpo-badpolicy01 + labels: + appPriority: Mission-Critical +spec: + comment: My sample custom backup policy + frequency: '@daily' + subFrequency: + minutes: [30] + hours: [22,7] + weekdays: [5] + days: [15] + retention: + daily: 14 + weekly: 4 + monthly: 6 + actions: + - action: backup + - action: export + exportParameters: + frequency: '@monthly' + profile: + name: my-profile + namespace: kasten-io + exportData: + enabled: true + retention: + monthly: 12 + yearly: 5 + selector: + matchLabels: + k10.kasten.io/appNamespace: sampleApp \ No newline at end of file diff --git a/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-good-policy.yaml b/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-good-policy.yaml new file mode 100644 index 000000000..8acf13284 --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.chainsaw-test/k10-good-policy.yaml @@ -0,0 +1,34 @@ +apiVersion: config.kio.kasten.io/v1alpha1 +kind: Policy +metadata: + name: k10-hourlyrpo-goodpolicy01 + labels: + appPriority: Mission-Critical +spec: + comment: My sample custom backup policy + frequency: '@hourly' + subFrequency: + minutes: [30] + hours: [22,7] + weekdays: [5] + days: [15] + retention: + daily: 14 + weekly: 4 + monthly: 6 + actions: + - action: backup + - action: export + exportParameters: + frequency: '@monthly' + profile: + name: my-profile + namespace: kasten-io + exportData: + enabled: true + retention: + monthly: 12 + yearly: 5 + selector: + matchLabels: + k10.kasten.io/appNamespace: sampleApp \ No newline at end of file diff --git a/kasten-cel/k10-hourly-rpo/.chainsaw-test/policy-ready.yaml b/kasten-cel/k10-hourly-rpo/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..3fa1c7221 --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-policy-hourly-rpo +status: + ready: true diff --git a/kasten-cel/k10-hourly-rpo/.kyverno-test/backup-export-policy.yaml b/kasten-cel/k10-hourly-rpo/.kyverno-test/backup-export-policy.yaml new file mode 100644 index 000000000..96430f81a --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.kyverno-test/backup-export-policy.yaml @@ -0,0 +1,73 @@ +# An example compliant K10 Policy +apiVersion: config.kio.kasten.io/v1alpha1 +kind: Policy +metadata: + name: hourly-policy + namespace: kasten-io + labels: + appPriority: Mission-Critical +spec: + comment: My sample custom backup policy + frequency: '@hourly' # change this to @daily to test the 'audit_mission_critical_RPO' policy + subFrequency: + minutes: [30] + hours: [22,7] + weekdays: [5] + days: [15] + retention: + daily: 14 + weekly: 4 + monthly: 6 + actions: + - action: backup + - action: export # comment this line out to test 'enforce_3-2-1' policy + exportParameters: + frequency: '@monthly' + profile: + name: my-profile + namespace: kasten-io + exportData: + enabled: true + retention: + monthly: 12 + yearly: 5 + selector: + matchLabels: + k10.kasten.io/appNamespace: sampleApp +--- +# An example compliant K10 Policy +apiVersion: config.kio.kasten.io/v1alpha1 +kind: Policy +metadata: + name: daily-policy + namespace: kasten-io + labels: + appPriority: Mission-Critical +spec: + comment: My sample custom backup policy + frequency: '@daily' # change this to @daily to test the 'audit_mission_critical_RPO' policy + subFrequency: + minutes: [30] + hours: [22,7] + weekdays: [5] + days: [15] + retention: + daily: 14 + weekly: 4 + monthly: 6 + actions: + - action: backup + - action: export # comment this line out to test 'enforce_3-2-1' policy + exportParameters: + frequency: '@monthly' + profile: + name: my-profile + namespace: kasten-io + exportData: + enabled: true + retention: + monthly: 12 + yearly: 5 + selector: + matchLabels: + k10.kasten.io/appNamespace: sampleApp diff --git a/kasten-cel/k10-hourly-rpo/.kyverno-test/kyverno-test.yaml b/kasten-cel/k10-hourly-rpo/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..965e355f5 --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,21 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: kyverno_data_protection_tests +policies: +- ../k10-hourly-rpo.yaml +resources: +- backup-export-policy.yaml +results: +- kind: Policy + policy: k10-policy-hourly-rpo + resources: + - daily-policy + result: fail + rule: k10-policy-hourly-rpo +- kind: Policy + policy: k10-policy-hourly-rpo + resources: + - hourly-policy + result: pass + rule: k10-policy-hourly-rpo diff --git a/kasten-cel/k10-hourly-rpo/artifacthub-pkg.yml b/kasten-cel/k10-hourly-rpo/artifacthub-pkg.yml new file mode 100644 index 000000000..bffb28b92 --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: k10-hourly-rpo-cel +version: 1.0.0 +displayName: Check Hourly RPO in CEL expressions +description: >- + K10 Policy resources can be educated to adhere to common Recovery Point Objective (RPO) best practices. This policy is advising to use an RPO frequency that with hourly granularity if it has the appPriority: Mission Critical +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/kasten-cel/k10-hourly-rpo/k10-hourly-rpo.yaml + ``` +keywords: + - kyverno + - Kasten K10 by Veeam + - CEL Expressions +readme: | + K10 Policy resources can be educated to adhere to common Recovery Point Objective (RPO) best practices. This policy is advising to use an RPO frequency that with hourly granularity if it has the appPriority: Mission Critical + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Kasten K10 by Veeam in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Policy" +digest: 4c95862e422636b4900103e9620ed8e41d4cafd86984a1d22e81f35767bb0eef +createdAt: "2024-05-12T07:07:31Z" + diff --git a/kasten-cel/k10-hourly-rpo/k10-hourly-rpo.yaml b/kasten-cel/k10-hourly-rpo/k10-hourly-rpo.yaml new file mode 100644 index 000000000..d5f62904f --- /dev/null +++ b/kasten-cel/k10-hourly-rpo/k10-hourly-rpo.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-policy-hourly-rpo + annotations: + policies.kyverno.io/title: Check Hourly RPO in CEL expressions + policies.kyverno.io/category: Kasten K10 by Veeam in CEL + 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: Policy + policies.kyverno.io/description: >- + K10 Policy resources can be educated to adhere to common Recovery Point Objective (RPO) best practices. + This policy is advising to use an RPO frequency that with hourly granularity if it has the appPriority: Mission Critical +spec: + validationFailureAction: Audit + rules: + - name: k10-policy-hourly-rpo + match: + any: + - resources: + kinds: + - config.kio.kasten.io/v1alpha1/Policy + operations: + - CREATE + - UPDATE + selector: + matchLabels: + appPriority: Mission-Critical + validate: + cel: + expressions: + - expression: "has(object.spec.frequency) && object.spec.frequency == '@hourly'" + message: "Mission Critical RPO frequency should use no shorter than @hourly frequency" + diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/chainsaw-test.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..8893c6007 --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,33 @@ +# 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: k10-validate-ns-by-preset-label +spec: + steps: + - name: step-01 + try: + - apply: + file: ../k10-validate-ns-by-preset-label.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: k10-validate-ns-by-preset-label + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - assert: + file: crd-assert.yaml + - name: step-02 + try: + - apply: + file: ns-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: ns-bad.yaml diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/crd-assert.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/crd-assert.yaml new file mode 100755 index 000000000..d660e00cb --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/crd-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: policies.config.kio.kasten.io +spec: {} +status: + acceptedNames: + kind: Policy + listKind: PolicyList + plural: policies + singular: policy + storedVersions: + - v1alpha1 diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-bad.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-bad.yaml new file mode 100644 index 000000000..baf81215b --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-bad.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-badns01 + labels: + dataprotection: foo-bar +--- +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-badns02 \ No newline at end of file diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-good.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-good.yaml new file mode 100644 index 000000000..f9fcdc245 --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/ns-good.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-goodns01 + labels: + dataprotection: gold +--- +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-goodns02 + labels: + dataprotection: silver +--- +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-goodns03 + labels: + dataprotection: bronze +--- +apiVersion: v1 +kind: Namespace +metadata: + name: k10-validatens-goodns04 + labels: + dataprotection: none \ No newline at end of file diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/policy-ready.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..27e86f51b --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-validate-ns-by-preset-label +status: + ready: true diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/kyverno-test.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..440c95426 --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,24 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: k10-validate-ns-by-preset-label-test +policies: +- ../k10-validate-ns-by-preset-label.yaml +resources: +- test-resource.yaml +results: +- kind: Namespace + policy: k10-validate-ns-by-preset-label + resources: + - namespace-invalid + result: fail + rule: k10-validate-ns-by-preset-label +- kind: Namespace + policy: k10-validate-ns-by-preset-label + resources: + - namespace-gold + - namespace-silver + - namespace-bronze + - namespace-none + result: pass + rule: k10-validate-ns-by-preset-label diff --git a/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/test-resource.yaml b/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/test-resource.yaml new file mode 100644 index 000000000..f5dc36f2b --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/.kyverno-test/test-resource.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: namespace-gold + labels: + dataprotection: gold +--- +apiVersion: v1 +kind: Namespace +metadata: + name: namespace-silver + labels: + dataprotection: silver +--- +apiVersion: v1 +kind: Namespace +metadata: + name: namespace-bronze + labels: + dataprotection: bronze +--- +apiVersion: v1 +kind: Namespace +metadata: + name: namespace-none + labels: + dataprotection: none +--- +apiVersion: v1 +kind: Namespace +metadata: + name: namespace-invalid \ No newline at end of file diff --git a/kasten-cel/k10-validate-ns-by-preset-label/artifacthub-pkg.yml b/kasten-cel/k10-validate-ns-by-preset-label/artifacthub-pkg.yml new file mode 100644 index 000000000..c1ec63ef0 --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: k10-validate-ns-by-preset-label-cel +version: 1.0.0 +displayName: Validate Data Protection by Preset Label in CEL expressions +description: >- + Kubernetes applications are typically deployed into a single, logical namespace. Kasten K10 policies will discover and protect all resources within the selected namespace(s). This policy ensures all new namespaces include a label referencing a valid K10 SLA (Policy Preset) for data protection. This policy can be used in combination with generate ClusterPolicy to automatically create a K10 policy based on the specified SLA. The combination ensures that new applications are not inadvertently left unprotected. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/kasten-cel/k10-validate-ns-by-preset-label/k10-validate-ns-by-preset-label.yaml + ``` +keywords: + - kyverno + - Kasten K10 by Veeam + - CEL Expressions +readme: | + Kubernetes applications are typically deployed into a single, logical namespace. Kasten K10 policies will discover and protect all resources within the selected namespace(s). This policy ensures all new namespaces include a label referencing a valid K10 SLA (Policy Preset) for data protection. This policy can be used in combination with generate ClusterPolicy to automatically create a K10 policy based on the specified SLA. The combination ensures that new applications are not inadvertently left unprotected. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Kasten K10 by Veeam in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Namespace" +digest: e58ab4c2018542a6acd5e97446b09cf04cec26425b9a29f0207c518310c449f3 +createdAt: "2024-05-12T07:09:08Z" + diff --git a/kasten-cel/k10-validate-ns-by-preset-label/k10-validate-ns-by-preset-label.yaml b/kasten-cel/k10-validate-ns-by-preset-label/k10-validate-ns-by-preset-label.yaml new file mode 100644 index 000000000..4668e742a --- /dev/null +++ b/kasten-cel/k10-validate-ns-by-preset-label/k10-validate-ns-by-preset-label.yaml @@ -0,0 +1,42 @@ +#NOTE: This example assumes that K10 policy presets named "gold", "silver", and "bronze" have been pre-created and K10 was deployed into the `kasten-io` namespace. +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: k10-validate-ns-by-preset-label + annotations: + policies.kyverno.io/title: Validate Data Protection by Preset Label in CEL expressions + policies.kyverno.io/category: Kasten K10 by Veeam in CEL + policies.kyverno.io/subject: Namespace + 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: >- + Kubernetes applications are typically deployed into a single, logical namespace. + Kasten K10 policies will discover and protect all resources within the selected namespace(s). + This policy ensures all new namespaces include a label referencing a valid K10 SLA + (Policy Preset) for data protection.This policy can be used in combination with generate + ClusterPolicy to automatically create a K10 policy based on the specified SLA. + The combination ensures that new applications are not inadvertently left unprotected. +spec: + validationFailureAction: Audit + rules: + - name: k10-validate-ns-by-preset-label + match: + any: + - resources: + kinds: + - Namespace + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: "has(object.metadata.labels) && has(object.metadata.labels.dataprotection) && object.metadata.labels.dataprotection in ['gold', 'silver', 'bronze', 'none']" + message: >- + Namespaces must specify a "dataprotection" label with a value corresponding to a Kasten K10 SLA: + + "gold" - + "silver" - + "bronze" - + "none" - No local snapshots or backups diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/chainsaw-test.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..f948a1a98 --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: require-kubecost-labels +spec: + steps: + - name: step-01 + try: + - apply: + file: ../require-kubecost-labels.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: require-kubecost-labels + spec: + validationFailureAction: Enforce + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod-good.yaml + - apply: + file: podcontroller-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: pod-bad.yaml + - apply: + expect: + - check: + ($error != null): true + file: podcontroller-bad.yaml diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-bad.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-bad.yaml new file mode 100644 index 000000000..68e1fe0a1 --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-bad.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + name: badpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + env: foo + name: badpod02 +spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + owner: foo + team: bar + department: foo + app: bar + name: badpod03 +spec: + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-good.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-good.yaml new file mode 100644 index 000000000..50ec73c0a --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/pod-good.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + foo: bar + owner: foo + team: bar + department: foo + app: bar + env: foo + name: goodpod01 +spec: + containers: + - name: busybox + image: busybox:1.35 \ No newline at end of file diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml new file mode 100644 index 000000000..44277f3ba --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + foo: bar + template: + metadata: + labels: + foo: bar + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: baddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + owner: "foo" + template: + metadata: + labels: + owner: "foo" + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + foo: bar + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: badcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + owner: "foo" + team: "foo" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-good.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-good.yaml new file mode 100644 index 000000000..4e85726df --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/podcontroller-good.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy01 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + owner: "foo" + team: "foo" + department: "foo" + env: "foo" + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: busybox + name: gooddeploy02 +spec: + replicas: 1 + selector: + matchLabels: + app: busybox + template: + metadata: + labels: + app: busybox + owner: "foo" + team: "foo" + department: "foo" + env: "foo" + foo: bar + spec: + containers: + - name: busybox + image: busybox:1.35 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob01 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + owner: "foo" + team: "foo" + department: "foo" + app: "foo" + env: "foo" + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: goodcronjob02 +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + owner: "foo" + team: "foo" + department: "foo" + app: "foo" + env: "foo" + foo: bar + spec: + containers: + - name: hello + image: busybox:1.35 + command: + - "sleep" + - "3600" + restartPolicy: OnFailure \ No newline at end of file diff --git a/kubecost-cel/require-kubecost-labels/.chainsaw-test/policy-ready.yaml b/kubecost-cel/require-kubecost-labels/.chainsaw-test/policy-ready.yaml new file mode 100755 index 000000000..ed44c7cf3 --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.chainsaw-test/policy-ready.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-kubecost-labels +status: + ready: true diff --git a/kubecost-cel/require-kubecost-labels/.kyverno-test/kyverno-test.yaml b/kubecost-cel/require-kubecost-labels/.kyverno-test/kyverno-test.yaml new file mode 100644 index 000000000..41e2fbf5f --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.kyverno-test/kyverno-test.yaml @@ -0,0 +1,25 @@ +apiVersion: cli.kyverno.io/v1alpha1 +kind: Test +metadata: + name: require-kubecost-labels +policies: +- ../require-kubecost-labels.yaml +resources: +- resource.yaml +results: +- kind: Pod + policy: require-kubecost-labels + resources: + - badpod01 + - badpod02 + - badpod03 + - badpod04 + - badpod05 + result: fail + rule: require-labels +- kind: Pod + policy: require-kubecost-labels + resources: + - goodpod + result: pass + rule: require-labels diff --git a/kubecost-cel/require-kubecost-labels/.kyverno-test/resource.yaml b/kubecost-cel/require-kubecost-labels/.kyverno-test/resource.yaml new file mode 100644 index 000000000..17ab732f0 --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/.kyverno-test/resource.yaml @@ -0,0 +1,73 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goodpod + labels: + owner: John Doe + team: falcon + department: eng + app: redis + env: prod2 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod01 +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod02 + labels: + owner: John Doe +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod03 + labels: + owner: John Doe + team: falcon +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod04 + labels: + owner: John Doe + team: falcon + department: eng +spec: + containers: + - image: busybox:1.35 + name: busybox +--- +apiVersion: v1 +kind: Pod +metadata: + name: badpod05 + labels: + owner: John Doe + team: falcon + department: eng + app: redis +spec: + containers: + - image: busybox:1.35 + name: busybox diff --git a/kubecost-cel/require-kubecost-labels/artifacthub-pkg.yml b/kubecost-cel/require-kubecost-labels/artifacthub-pkg.yml new file mode 100644 index 000000000..bfae83d11 --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/artifacthub-pkg.yml @@ -0,0 +1,24 @@ +name: require-kubecost-labels-cel +version: 1.0.0 +displayName: Require Kubecost Labels in CEL expressions +description: >- + Kubecost can use labels assigned to Pods in order to track and display cost allocation in a granular way. These labels, which can be customized, can be used to organize and group workloads in different ways. This policy requires that the labels `owner`, `team`, `department`, `app`, and `env` are all defined on Pods. With Kyverno autogen enabled (absence of the annotation `pod-policies.kyverno.io/autogen-controllers=none`), these labels will also be required for all Pod controllers. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/kubecost-cel/require-kubecost-labels/require-kubecost-labels.yaml + ``` +keywords: + - kyverno + - Kubecost + - CEL Expressions +readme: | + Kubecost can use labels assigned to Pods in order to track and display cost allocation in a granular way. These labels, which can be customized, can be used to organize and group workloads in different ways. This policy requires that the labels `owner`, `team`, `department`, `app`, and `env` are all defined on Pods. With Kyverno autogen enabled (absence of the annotation `pod-policies.kyverno.io/autogen-controllers=none`), these labels will also be required for all Pod controllers. + + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Kubecost in CEL" + kyverno/kubernetesVersion: "1.26-1.27" + kyverno/subject: "Pod,Label" +digest: e7dc12ab8d4fa467c23bc117db5c9e33e5e0d804c597ee0d88fb9f55f11ab535 +createdAt: "2024-05-12T06:59:59Z" + diff --git a/kubecost-cel/require-kubecost-labels/require-kubecost-labels.yaml b/kubecost-cel/require-kubecost-labels/require-kubecost-labels.yaml new file mode 100644 index 000000000..32ca0dccb --- /dev/null +++ b/kubecost-cel/require-kubecost-labels/require-kubecost-labels.yaml @@ -0,0 +1,43 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-kubecost-labels + annotations: + policies.kyverno.io/title: Require Kubecost Labels in CEL expressions + policies.kyverno.io/category: Kubecost in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod, Label + kyverno.io/kyverno-version: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Kubecost can use labels assigned to Pods in order to track and display + cost allocation in a granular way. These labels, which can be customized, can be used + to organize and group workloads in different ways. This policy requires that the labels + `owner`, `team`, `department`, `app`, and `env` are all defined on Pods. With Kyverno + autogen enabled (absence of the annotation `pod-policies.kyverno.io/autogen-controllers=none`), + these labels will also be required for all Pod controllers. +spec: + validationFailureAction: Audit + background: true + rules: + - name: require-labels + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + validate: + cel: + expressions: + - expression: >- + has(object.metadata.labels) && + has(object.metadata.labels.owner) && object.metadata.labels.owner != '' && + has(object.metadata.labels.team) && object.metadata.labels.team != '' && + has(object.metadata.labels.department) && object.metadata.labels.department != '' && + has(object.metadata.labels.app) && object.metadata.labels.app != '' && + has(object.metadata.labels.env) && object.metadata.labels.env != '' + message: "The Kubecost labels `owner`, `team`, `department`, `app`, and `env` are all required for Pods." + diff --git a/kubecost/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml b/kubecost/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml index d8db785f5..44277f3ba 100644 --- a/kubecost/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml +++ b/kubecost/require-kubecost-labels/.chainsaw-test/podcontroller-bad.yaml @@ -8,7 +8,7 @@ spec: replicas: 1 selector: matchLabels: - app: busybox + foo: bar template: metadata: labels: @@ -28,7 +28,7 @@ spec: replicas: 1 selector: matchLabels: - app: busybox + owner: "foo" template: metadata: labels: