From 7a81e34effa52135bf22409b3c6aa1c09c9d815d Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 16 Jun 2025 12:42:12 +0000 Subject: [PATCH] feat: basic Kyverno policies chart, AWS Pod Identity policy --- charts/kubezero-policy/Chart.yaml | 3 + charts/kubezero-policy/README.md | 19 +++++ .../charts/policies/Chart.yaml | 18 +++++ .../charts/policies/README.md.gotmpl | 18 +++++ .../templates/aws/iam-pod-identity.yaml | 69 +++++++++++++++++++ .../templates/disallow-cri-sock-mount.yaml | 62 +++++++++++++++++ .../kubezero-policy/charts/policies/update.sh | 9 +++ .../charts/policies/values.yaml | 6 ++ charts/kubezero-policy/values.yaml | 3 +- charts/kubezero/templates/policy.yaml | 8 +++ charts/kubezero/values.yaml | 10 +-- docs/kube-bench.yaml | 9 ++- 12 files changed, 226 insertions(+), 8 deletions(-) create mode 100644 charts/kubezero-policy/charts/policies/Chart.yaml create mode 100644 charts/kubezero-policy/charts/policies/README.md.gotmpl create mode 100644 charts/kubezero-policy/charts/policies/templates/aws/iam-pod-identity.yaml create mode 100644 charts/kubezero-policy/charts/policies/templates/disallow-cri-sock-mount.yaml create mode 100755 charts/kubezero-policy/charts/policies/update.sh create mode 100644 charts/kubezero-policy/charts/policies/values.yaml diff --git a/charts/kubezero-policy/Chart.yaml b/charts/kubezero-policy/Chart.yaml index 54dc8009..f763810b 100644 --- a/charts/kubezero-policy/Chart.yaml +++ b/charts/kubezero-policy/Chart.yaml @@ -20,4 +20,7 @@ dependencies: version: 3.4.2 repository: https://kyverno.github.io/kyverno/ condition: kyverno.enabled + - name: policies + version: 0.1.0 + condition: policies.enabled kubeVersion: ">= 1.30.0-0" diff --git a/charts/kubezero-policy/README.md b/charts/kubezero-policy/README.md index 8f74c6ae..7d4598c3 100644 --- a/charts/kubezero-policy/README.md +++ b/charts/kubezero-policy/README.md @@ -18,6 +18,7 @@ Kubernetes: `>= 1.30.0-0` | Repository | Name | Version | |------------|------|---------| +| | policies | 0.1.0 | | https://cdn.zero-downtime.net/charts/ | kubezero-lib | 0.2.1 | | https://kyverno.github.io/kyverno/ | kyverno | 3.4.2 | @@ -27,4 +28,22 @@ Kubernetes: `>= 1.30.0-0` | Key | Type | Default | Description | |-----|------|---------|-------------| +| kyverno.admissionController.revisionHistoryLimit | int | `2` | | +| kyverno.backgroundController.revisionHistoryLimit | int | `2` | | +| kyverno.cleanupController.rbac.clusterRole.extraResources[0].apiGroups[0] | string | `"postgresql.cnpg.io"` | | +| kyverno.cleanupController.rbac.clusterRole.extraResources[0].resources[0] | string | `"backups"` | | +| kyverno.cleanupController.rbac.clusterRole.extraResources[0].verbs[0] | string | `"delete"` | | +| kyverno.cleanupController.rbac.clusterRole.extraResources[0].verbs[1] | string | `"list"` | | +| kyverno.cleanupController.rbac.clusterRole.extraResources[0].verbs[2] | string | `"watch"` | | +| kyverno.cleanupController.revisionHistoryLimit | int | `2` | | +| kyverno.config.preserve | bool | `false` | | +| kyverno.config.webhookAnnotations."argocd.argoproj.io/installation-id" | string | `"KubeZero-ArgoCD"` | | +| kyverno.crds.migration.enabled | bool | `false` | | | kyverno.enabled | bool | `false` | | +| kyverno.features.logging.format | string | `"json"` | | +| kyverno.grafana.enabled | bool | `false` | | +| kyverno.policyReportsCleanup.enabled | bool | `false` | | +| kyverno.reportsController.enabled | bool | `false` | | +| kyverno.reportsController.revisionHistoryLimit | int | `2` | | +| kyverno.webhooksCleanup.autoDeleteWebhooks.enabled | bool | `true` | | +| kyverno.webhooksCleanup.enabled | bool | `true` | | diff --git a/charts/kubezero-policy/charts/policies/Chart.yaml b/charts/kubezero-policy/charts/policies/Chart.yaml new file mode 100644 index 00000000..98c6c93b --- /dev/null +++ b/charts/kubezero-policy/charts/policies/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: policies +description: KubeZero collection of Kyverno policies +type: application +version: 0.1.0 +home: https://kubezero.com +icon: https://cdn.zero-downtime.net/assets/kubezero/logo-small-64.png +keywords: + - kubezero + - kyverno +maintainers: + - name: Stefan Reimer + email: stefan@zero-downtime.net +dependencies: + - name: kubezero-lib + version: 0.2.1 + repository: https://cdn.zero-downtime.net/charts/ +kubeVersion: ">= 1.30.0-0" diff --git a/charts/kubezero-policy/charts/policies/README.md.gotmpl b/charts/kubezero-policy/charts/policies/README.md.gotmpl new file mode 100644 index 00000000..11858378 --- /dev/null +++ b/charts/kubezero-policy/charts/policies/README.md.gotmpl @@ -0,0 +1,18 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +# Kyverno + +{{ template "chart.valuesSection" . }} diff --git a/charts/kubezero-policy/charts/policies/templates/aws/iam-pod-identity.yaml b/charts/kubezero-policy/charts/policies/templates/aws/iam-pod-identity.yaml new file mode 100644 index 00000000..3119fc5d --- /dev/null +++ b/charts/kubezero-policy/charts/policies/templates/aws/iam-pod-identity.yaml @@ -0,0 +1,69 @@ +{{- if .Values.aws.enabled }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: add-aws-iam-oidc-mapping + annotations: + policies.kyverno.io/title: AWS Pod Identity + policies.kyverno.io/category: aws + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.31" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Pods having a service account annotated with \"kubezero.com/aws-iam-role-arn\" + will get the required environment variables as well as volumes injected + to make the SDKs automatically find and use the IAM role. +spec: + useServerSideApply: true + background: false + rules: + - name: add-aws-iam-oidc-mapping + context: + - name: saAnnotations + apiCall: + urlPath: "/api/v1/namespaces/{{`{{request.namespace}}`}}/serviceaccounts/{{`{{request.object.spec.serviceAccountName}}`}}" + jmesPath: "metadata.annotations || ''" + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + preconditions: + all: + - key: "{{`{{request.object.spec.serviceAccountName || '' }}`}}" + operator: NotEquals + value: "" + - key: "{{`{{ saAnnotations.\"kubezero.com/aws-iam-role-arn\" || '' }}`}}" + operator: NotEquals + value: "" + mutate: + foreach: + - list: "request.object.spec.containers" + patchStrategicMerge: + spec: + containers: + - (name): "{{`{{ element.name }}`}}" + env: + - name: AWS_REGION + value: {{ .Values.aws.region }} + - name: AWS_ROLE_ARN + value: "{{`{{ saAnnotations.\"kubezero.com/aws-iam-role-arn\" }}`}}" + - name: AWS_WEB_IDENTITY_TOKEN_FILE + value: "/var/run/secrets/sts.amazonaws.com/serviceaccount/token" + - name: AWS_STS_REGIONAL_ENDPOINTS + value: regional + volumeMounts: + - name: aws-token + mountPath: "/var/run/secrets/sts.amazonaws.com/serviceaccount/" + readOnly: true + volumes: + - name: aws-token + projected: + sources: + - serviceAccountToken: + path: token + expirationSeconds: 86400 + audience: "sts.amazonaws.com" +{{- end }} diff --git a/charts/kubezero-policy/charts/policies/templates/disallow-cri-sock-mount.yaml b/charts/kubezero-policy/charts/policies/templates/disallow-cri-sock-mount.yaml new file mode 100644 index 00000000..ce525981 --- /dev/null +++ b/charts/kubezero-policy/charts/policies/templates/disallow-cri-sock-mount.yaml @@ -0,0 +1,62 @@ +{{- if .Values.bestPractices.enabled }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-container-sock-mounts + annotations: + policies.kyverno.io/title: Disallow CRI socket mounts in CEL expressions + policies.kyverno.io/category: Best Practices, EKS Best Practices in CEL + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.11.0 + kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/description: >- + Container daemon socket bind mounts allows access to the container engine on the + node. This access can be used for privilege escalation and to manage containers + outside of Kubernetes, and hence should not be allowed. This policy validates that + the sockets used for CRI engines Docker, Containerd, and CRI-O are not used. In addition + to or replacement of this policy, preventing users from mounting the parent directories + (/var/run and /var) may be necessary to completely prevent socket bind mounts. +spec: + validationFailureAction: Audit + background: true + rules: + - name: validate-socket-mounts + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + validate: + cel: + variables: + - name: hasVolumes + expression: "!has(object.spec.volumes)" + - name: volumes + expression: "object.spec.volumes" + - name: volumesWithHostPath + expression: "variables.volumes.filter(volume, has(volume.hostPath))" + expressions: + - expression: >- + variables.hasVolumes || + variables.volumesWithHostPath.all(volume, !volume.hostPath.path.matches('/var/run/docker.sock')) + message: "Use of the Docker Unix socket is not allowed." + + - expression: >- + variables.hasVolumes || + variables.volumesWithHostPath.all(volume, !volume.hostPath.path.matches('/var/run/containerd/containerd.sock')) + message: "Use of the Containerd Unix socket is not allowed." + + - expression: >- + variables.hasVolumes || + variables.volumesWithHostPath.all(volume, !volume.hostPath.path.matches('/var/run/crio/crio.sock')) + message: "Use of the CRI-O Unix socket is not allowed." + + - expression: >- + variables.hasVolumes || + variables.volumesWithHostPath.all(volume, !volume.hostPath.path.matches('/var/run/cri-dockerd.sock')) + message: "Use of the Docker CRI socket is not allowed." +{{- end }} diff --git a/charts/kubezero-policy/charts/policies/update.sh b/charts/kubezero-policy/charts/policies/update.sh new file mode 100755 index 00000000..3f7c5736 --- /dev/null +++ b/charts/kubezero-policy/charts/policies/update.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -ex + +. ../../scripts/lib-update.sh + +login_ecr_public +update_helm + +update_docs diff --git a/charts/kubezero-policy/charts/policies/values.yaml b/charts/kubezero-policy/charts/policies/values.yaml new file mode 100644 index 00000000..d9535146 --- /dev/null +++ b/charts/kubezero-policy/charts/policies/values.yaml @@ -0,0 +1,6 @@ +bestPractices: + enabled: false + +aws: + enabled: false + region: us-west-2 diff --git a/charts/kubezero-policy/values.yaml b/charts/kubezero-policy/values.yaml index daaa5b49..3cc1bc45 100644 --- a/charts/kubezero-policy/values.yaml +++ b/charts/kubezero-policy/values.yaml @@ -5,7 +5,7 @@ kyverno: policyReportsCleanup: enabled: false webhooksCleanup: - enabled: false + enabled: true autoDeleteWebhooks: enabled: true @@ -51,7 +51,6 @@ kyverno: backgroundController: revisionHistoryLimit: 2 - enabled: false reportsController: revisionHistoryLimit: 2 diff --git a/charts/kubezero/templates/policy.yaml b/charts/kubezero/templates/policy.yaml index 3ce4b78d..0e17e960 100644 --- a/charts/kubezero/templates/policy.yaml +++ b/charts/kubezero/templates/policy.yaml @@ -23,6 +23,14 @@ kyverno: reportsController: serviceMonitor: enabled: {{ .Values.metrics.enabled }} + +policies: + {{- if eq .Values.global.platform "aws" }} + aws: + enabled: true + region: {{ .global.aws.region }} + {{- end }} + {{- end }} {{- define "policy-argo" }} diff --git a/charts/kubezero/values.yaml b/charts/kubezero/values.yaml index 91b1b319..5643f62a 100644 --- a/charts/kubezero/values.yaml +++ b/charts/kubezero/values.yaml @@ -30,11 +30,6 @@ addons: aws-eks-asg-rolling-update-handler: enabled: false -policy: - enabled: false - namespace: kyverno - targetRevision: 0.1.0 - network: enabled: true retain: true @@ -42,6 +37,11 @@ network: cilium: enabled: true +policy: + enabled: false + namespace: kyverno + targetRevision: 0.1.0 + cert-manager: enabled: false namespace: cert-manager diff --git a/docs/kube-bench.yaml b/docs/kube-bench.yaml index 2cd859cb..e48fc11f 100644 --- a/docs/kube-bench.yaml +++ b/docs/kube-bench.yaml @@ -1,4 +1,10 @@ ---- +#apiVersion: v1 +#kind: ServiceAccount +#metadata: +# name: kube-bench +# annotations: +# kubezero.com/aws-iam-role-arn: arn:aws:iam::123456789012:role/kube-bench +#--- apiVersion: batch/v1 kind: Job metadata: @@ -9,6 +15,7 @@ spec: labels: app: kube-bench spec: +# serviceAccountName: kube-bench containers: - command: ["kube-bench"] #args: