From 18060cbde651ffc70a4a647ddd8c03b2eba4dcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Stehl=C3=ADk?= Date: Fri, 12 May 2023 20:07:09 +0200 Subject: [PATCH] Test/test argo (#8) * test: Test Argo * test: Test Argo --- .github/workflows/helm-lint-test.yaml | 2 +- charts/test-chart/Chart.yaml | 11 +- charts/test-chart/README.md | 166 +++++++++++++++++- charts/test-chart/README.md.gotmpl | 162 ++++++++++++++++- .../ci/enable-categories-values.yaml | 7 + charts/test-chart/ci/test-values.yaml | 3 - charts/test-chart/templates/_helpers.tpl | 49 +++++- .../templates/other/blockStaleImages.yaml | 56 ++++++ .../templates/other/checkServiceAccount.yaml | 52 ++++++ .../disableAutomountServiceAccountToken.yaml | 71 ++++++++ ...isablePodAutomountServiceAccountToken.yaml | 52 ++++++ .../other/disableServiceDiscovery.yaml | 48 +++++ .../templates/other/disallowAllSecrets.yaml | 104 +++++++++++ .../other/disallowDefaultNamespace.yaml | 64 +++++++ .../other/disallowEmptyIngressHost.yaml | 47 +++++ .../templates/other/preventNakedPods.yaml | 54 ++++++ .../templates/other/protectNodeTaints.yaml | 60 +++++++ .../requireEncryptionAwsLoadBalancers.yaml | 51 ++++++ .../templates/other/requireLabels.yaml | 47 +++++ .../templates/other/requireRoRootFs.yaml | 49 ++++++ .../other/restrictImageRegistries.yaml | 48 +++++ .../other/restrictIngressWildcard.yaml | 59 +++++++ .../templates/other/restrictNodePort.yaml | 47 +++++ .../other/restrictServiceExternalIps.yaml | 49 ++++++ .../disallowHostNamespaces.yaml | 13 +- .../podSecurityBaseline/disallowHostPath.yaml | 48 +++++ .../disallowHostPorts.yaml | 57 ++++++ .../disallowPrivilegedContainers.yaml | 55 ++++++ .../disallowProcMount.yaml | 59 +++++++ .../podSecurityBaseline/disallowSELinux.yaml | 101 +++++++++++ .../podSecurityBaseline/restrictAppArmor.yaml | 52 ++++++ .../podSecurityBaseline/restrictSysctls.yaml | 56 ++++++ .../disallowCapabilitiesStrict.yaml | 85 +++++++++ .../disallowPrivilegeEscalation.yaml | 58 ++++++ .../requireRunAsNonRoot.yaml | 70 ++++++++ .../requireRunAsNonRootUser.yaml | 59 +++++++ .../restrictSeccompStrict.yaml | 81 +++++++++ .../restrictVolumeTypes.yaml | 62 +++++++ 38 files changed, 2183 insertions(+), 31 deletions(-) create mode 100644 charts/test-chart/ci/enable-categories-values.yaml delete mode 100644 charts/test-chart/ci/test-values.yaml create mode 100644 charts/test-chart/templates/other/blockStaleImages.yaml create mode 100644 charts/test-chart/templates/other/checkServiceAccount.yaml create mode 100644 charts/test-chart/templates/other/disableAutomountServiceAccountToken.yaml create mode 100644 charts/test-chart/templates/other/disablePodAutomountServiceAccountToken.yaml create mode 100644 charts/test-chart/templates/other/disableServiceDiscovery.yaml create mode 100644 charts/test-chart/templates/other/disallowAllSecrets.yaml create mode 100644 charts/test-chart/templates/other/disallowDefaultNamespace.yaml create mode 100644 charts/test-chart/templates/other/disallowEmptyIngressHost.yaml create mode 100644 charts/test-chart/templates/other/preventNakedPods.yaml create mode 100644 charts/test-chart/templates/other/protectNodeTaints.yaml create mode 100644 charts/test-chart/templates/other/requireEncryptionAwsLoadBalancers.yaml create mode 100644 charts/test-chart/templates/other/requireLabels.yaml create mode 100644 charts/test-chart/templates/other/requireRoRootFs.yaml create mode 100644 charts/test-chart/templates/other/restrictImageRegistries.yaml create mode 100644 charts/test-chart/templates/other/restrictIngressWildcard.yaml create mode 100644 charts/test-chart/templates/other/restrictNodePort.yaml create mode 100644 charts/test-chart/templates/other/restrictServiceExternalIps.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/disallowHostPath.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/disallowHostPorts.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/disallowPrivilegedContainers.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/disallowProcMount.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/disallowSELinux.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/restrictAppArmor.yaml create mode 100644 charts/test-chart/templates/podSecurityBaseline/restrictSysctls.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/disallowCapabilitiesStrict.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/disallowPrivilegeEscalation.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRoot.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRootUser.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/restrictSeccompStrict.yaml create mode 100644 charts/test-chart/templates/podSecurityRestricted/restrictVolumeTypes.yaml diff --git a/.github/workflows/helm-lint-test.yaml b/.github/workflows/helm-lint-test.yaml index 624d8bd..4ca04ed 100644 --- a/.github/workflows/helm-lint-test.yaml +++ b/.github/workflows/helm-lint-test.yaml @@ -34,7 +34,7 @@ jobs: - name: Run chart-testing (lint) if: steps.list-changed.outputs.changed == 'true' - run: ct lint --target-branch ${{ github.event.repository.default_branch }} + run: ct lint --target-branch ${{ github.event.repository.default_branch }} --validate-maintainers=false - name: Create kind cluster if: steps.list-changed.outputs.changed == 'true' diff --git a/charts/test-chart/Chart.yaml b/charts/test-chart/Chart.yaml index bb28a4f..94c0a5f 100644 --- a/charts/test-chart/Chart.yaml +++ b/charts/test-chart/Chart.yaml @@ -15,13 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.1 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" +version: 0.5.0 +# Maintainers maintainers: - name: Balsir + email: somemail@gmail.com + url: https://somesite.com diff --git a/charts/test-chart/README.md b/charts/test-chart/README.md index 6e7070e..2ff2ec6 100644 --- a/charts/test-chart/README.md +++ b/charts/test-chart/README.md @@ -2,11 +2,167 @@ A Helm chart for Kubernetes -![Version: 0.2.1](https://img.shields.io/badge/Version-0.2.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) +![Version: 0.5.0](https://img.shields.io/badge/Version-0.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) -## About -<$chart-name> Helm chart -Testiiing +## Description +Helm chart to deploy Kyverno policies. +Policy categories: +- **podSecurityBaseline** - https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline +- **podSecurityRestricted** - https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted +- **other** + +## Installation +````shell +helm repo add kyverno-policies https://lablabs.github.io/kyverno-policies/ +helm install kyverno-policies kyverno-policies/kyverno-policies +```` + +## How-to +### Enable or disable policies +#### Enable a policy +````yaml +policies: + myPolicy: + enabled: true +```` +#### Enable a category +````yaml +# All policies within the category will be deployed +policyCategories: + myCategory: + enabled: true +```` + +#### Disable a policy or category +In case you want to deploy an entire category except for just a few policies, you can explicitly disable the unwanted +policies by setting their `enabled` value to `false` +````yaml +# Category myCategory is enabled +policyCategories: + myCategory: + enabled: true + +# The policy myPolicy is part of myCategory. By setting enabled: false, it will not be deployed even if the category is enabled. +policies: + myPolicy: + enabled: false +```` +The following table shows the results of possible combinations for the `enabled` values on the policy(p) and category(c) level. +`true` means policy will be deployed, `false` means policy will not be deployed. Policy value has precedence over category value. + +| enabled | true(c) | false(c) | no value(c) | +|-------------|---------|----------|-------------| +| true(p) | true | true | true | +| false(p) | false | false | false | +| no value(p) | true | false | false | + +### Set attributes +#### Set `validationFailureAction for a policy +````yaml +policies: + myPolicy: + validationFailureAction: Enforce +```` +#### Set validationFailureAction for a category +````yaml +policyCategories: + myCategory: + validationFailureAction: Enforce +```` +#### Set exclude block for a policy +````yaml +# Excludes namespace kube-system from rule validation +policies: + myPolicy: + exclude: + any: + - resources: + namespaces: + - kube-system +```` +#### Override policy rules +In case you want to override the entire `rules` block of a particular policy, set `.Values.policies.myPolicy.rulesOverride`. +````yaml +# Excludes namespace kube-system from rule validation +policies: + myPolicy: + rulesOverride: + - name: my-rule + match: ... +```` + +### Value priority +Most values are overridden in the following order of priority, from highest to lowest: +1. Policy +2. Category +3. Chart +#### Example +````yaml +# Chart setting +validationFailureAction: Audit + +# Category setting +# All policies within myCategory will have validationFailureAction set to Enforce +policyCategories: + myCategory: + validationFailureAction: Enforce + +# Even if myPolicy is part of myCategory, validationFailureAction will be Audit +policies: + myPolicy: + validationFailureAction: Audit +```` + +### Deploy custom policie +If you have custom policie you would like to deploy as part of the Helm release, provide their manifests in `.Values.extraManifests`: +````yaml +extraManifests: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: # metadata + spec: # spec +```` + +## Adding a new policy +1. Create your policy manifest. The policy should ideally be a ClusterPolicy +2. Place the policy template in its appropriate category directory +3. Override `$name` and `$category` variables. `$name` should match the file name, `category` should match the directory. +````yaml +{{- $name := "myPolicy" }} +{{- $category := "myCategory" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +# The policy goes here +{{- end }} +```` +4. Provide useful [Kyverno annotations](https://github.com/kyverno/policies/wiki/Kyverno-annotations) +5. [Policy settings](https://kyverno.io/docs/writing-policies/policy-settings/) are rendered via the kyverno-policies.policySettings template within _helpers.tpl. If your policy setting is not listed yet, add it there with appropriate overrides. +6. Add the `rules` block +````yaml + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} +# Your rules go here +{{- end }} +```` +7. Allow override of the `exclude` block within your rules (if appropriate) +````yaml +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} +```` +8. Add your policy and/or category to values.yaml +````yaml +policyCategories: + myCategory: {} + +policies: + myPolicy: {} +```` +9. Document your changes ## Values @@ -27,7 +183,7 @@ Testiiing | Name | Email | Url | | ---- | ------ | --- | -| Balsir | | | +| Balsir | | | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/charts/test-chart/README.md.gotmpl b/charts/test-chart/README.md.gotmpl index da6d7c9..1985f4b 100644 --- a/charts/test-chart/README.md.gotmpl +++ b/charts/test-chart/README.md.gotmpl @@ -4,9 +4,165 @@ {{ template "chart.badgesSection" . }} -## About -<$chart-name> Helm chart -Testiiing +## Description +Helm chart to deploy Kyverno policies. +Policy categories: +- **podSecurityBaseline** - https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline +- **podSecurityRestricted** - https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted +- **other** + +## Installation +````shell +helm repo add kyverno-policies https://lablabs.github.io/kyverno-policies/ +helm install kyverno-policies kyverno-policies/kyverno-policies +```` + +## How-to +### Enable or disable policies +#### Enable a policy +````yaml +policies: + myPolicy: + enabled: true +```` +#### Enable a category +````yaml +# All policies within the category will be deployed +policyCategories: + myCategory: + enabled: true +```` + +#### Disable a policy or category +In case you want to deploy an entire category except for just a few policies, you can explicitly disable the unwanted +policies by setting their `enabled` value to `false` +````yaml +# Category myCategory is enabled +policyCategories: + myCategory: + enabled: true + +# The policy myPolicy is part of myCategory. By setting enabled: false, it will not be deployed even if the category is enabled. +policies: + myPolicy: + enabled: false +```` +The following table shows the results of possible combinations for the `enabled` values on the policy(p) and category(c) level. +`true` means policy will be deployed, `false` means policy will not be deployed. Policy value has precedence over category value. + +| enabled | true(c) | false(c) | no value(c) | +|-------------|---------|----------|-------------| +| true(p) | true | true | true | +| false(p) | false | false | false | +| no value(p) | true | false | false | + +### Set attributes +#### Set `validationFailureAction for a policy +````yaml +policies: + myPolicy: + validationFailureAction: Enforce +```` +#### Set validationFailureAction for a category +````yaml +policyCategories: + myCategory: + validationFailureAction: Enforce +```` +#### Set exclude block for a policy +````yaml +# Excludes namespace kube-system from rule validation +policies: + myPolicy: + exclude: + any: + - resources: + namespaces: + - kube-system +```` +#### Override policy rules +In case you want to override the entire `rules` block of a particular policy, set `.Values.policies.myPolicy.rulesOverride`. +````yaml +# Excludes namespace kube-system from rule validation +policies: + myPolicy: + rulesOverride: + - name: my-rule + match: ... +```` + +### Value priority +Most values are overridden in the following order of priority, from highest to lowest: +1. Policy +2. Category +3. Chart +#### Example +````yaml +# Chart setting +validationFailureAction: Audit + +# Category setting +# All policies within myCategory will have validationFailureAction set to Enforce +policyCategories: + myCategory: + validationFailureAction: Enforce + +# Even if myPolicy is part of myCategory, validationFailureAction will be Audit +policies: + myPolicy: + validationFailureAction: Audit +```` + +### Deploy custom policie +If you have custom policie you would like to deploy as part of the Helm release, provide their manifests in `.Values.extraManifests`: +````yaml +extraManifests: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: # metadata + spec: # spec +```` + +## Adding a new policy +1. Create your policy manifest. The policy should ideally be a ClusterPolicy +2. Place the policy template in its appropriate category directory +3. Override `$name` and `$category` variables. `$name` should match the file name, `category` should match the directory. +````yaml +{{`{{- $name := "myPolicy" }}`}} +{{`{{- $category := "myCategory" }}`}} +{{`{{- $policyValues := get .Values.policies $name }}`}} +{{`{{- $categoryValues := get .Values.policyCategories $category }}`}} + +{{`{{- if include "kyverno-policies.enabled" (list $name $category $) }}`}} +# The policy goes here +{{`{{- end }}`}} +```` +4. Provide useful [Kyverno annotations](https://github.com/kyverno/policies/wiki/Kyverno-annotations) +5. [Policy settings](https://kyverno.io/docs/writing-policies/policy-settings/) are rendered via the kyverno-policies.policySettings template within _helpers.tpl. If your policy setting is not listed yet, add it there with appropriate overrides. +6. Add the `rules` block +````yaml + rules: +{{`{{- if $policyValues.rulesOverride }}`}} +{{`{{ toYaml $policyValues.rulesOverride | indent 4 }}`}} +{{`{{- else }}`}} +# Your rules go here +{{`{{- end }}`}} +```` +7. Allow override of the `exclude` block within your rules (if appropriate) +````yaml +{{`{{- if $policyValues.exclude }}`}} + exclude: {{`{{ toYaml $policyValues.exclude | nindent 8 }}`}} +{{`{{- end }}`}} +```` +8. Add your policy and/or category to values.yaml +````yaml +policyCategories: + myCategory: {} + +policies: + myPolicy: {} +```` +9. Document your changes {{ template "chart.valuesSection" . }} diff --git a/charts/test-chart/ci/enable-categories-values.yaml b/charts/test-chart/ci/enable-categories-values.yaml new file mode 100644 index 0000000..6af337f --- /dev/null +++ b/charts/test-chart/ci/enable-categories-values.yaml @@ -0,0 +1,7 @@ +policyCategories: + podSecurityBaseline: + enabled: true + podSecurityRestricted: + enabled: true + other: + enabled: true diff --git a/charts/test-chart/ci/test-values.yaml b/charts/test-chart/ci/test-values.yaml deleted file mode 100644 index 8d8ee09..0000000 --- a/charts/test-chart/ci/test-values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -policies: - disallowHostNamespaces: - enabled: true diff --git a/charts/test-chart/templates/_helpers.tpl b/charts/test-chart/templates/_helpers.tpl index 032e22e..e5c2309 100644 --- a/charts/test-chart/templates/_helpers.tpl +++ b/charts/test-chart/templates/_helpers.tpl @@ -31,7 +31,7 @@ Create chart name and version as used by the chart label. {{- end }} {{/* -Renders a value that contains template. Based on https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_tplvalues.tpl +Render a value that contains template. Based on https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_tplvalues.tpl Usage: {{ include "kyverno-policies.extraManifests" ( dict "value" .Values.path.to.the.Value "context" $) }} */}} @@ -42,3 +42,50 @@ Usage: {{- tpl (.value | toYaml) .context }} {{- end }} {{- end -}} + +{{/* +Check if a particular policy is enabled. +Usage: +{{ include "kyverno-policies.enabled" (list $name $category $) }} +*/}} +{{- define "kyverno-policies.enabled" -}} +{{- $name := index . 0 }} +{{- $category := index . 1 }} +{{- $ := index . 2 }} +{{- $policyValues := get $.Values.policies $name }} +{{- $categoryValues := get $.Values.policyCategories $category }} +{{- if hasKey $policyValues "enabled" }} + {{- if and true (index $policyValues "enabled") }} + {{- index $policyValues "enabled" }} + {{- else }} + {{- end }} +{{- else if hasKey $categoryValues "enabled" }} + {{- if and true (index $categoryValues "enabled") }} + {{- index $categoryValues "enabled" }} + {{- else }} + {{- end }} +{{- else }} +{{- end }} +{{- end -}} + +{{/* +Render default policy settings https://kyverno.io/docs/writing-policies/policy-settings/. +{{ include "kyverno-policies.policySettings" (list $name $category $) }} +*/}} +{{- define "kyverno-policies.policySettings" -}} +{{- $name := index . 0 }} +{{- $category := index . 1 }} +{{- $ := index . 2 }} +{{- $policyValues := get $.Values.policies $name }} +{{- $categoryValues := get $.Values.policyCategories $category }} + validationFailureAction: {{ coalesce $policyValues.validationFailureAction $categoryValues.validationFailureAction $.Values.validationFailureAction }} + validationFailureActionOverrides: {{ toYaml (coalesce $policyValues.validationFailureActionOverrides $categoryValues.validationFailureActionOverrides $.Values.validationFailureActionOverrides) | nindent 4 }} +{{- if hasKey $policyValues "background" }} + background: {{ $policyValues.background }} +{{- else if hasKey $categoryValues "background" }} + background: {{ $categoryValues.background }} +{{- else }} + background: {{ $.Values.background }} +{{- end }} + failurePolicy: {{ coalesce $policyValues.failurePolicy $categoryValues.failurePolicy $.Values.failurePolicy }} +{{- end -}} diff --git a/charts/test-chart/templates/other/blockStaleImages.yaml b/charts/test-chart/templates/other/blockStaleImages.yaml new file mode 100644 index 0000000..7814792 --- /dev/null +++ b/charts/test-chart/templates/other/blockStaleImages.yaml @@ -0,0 +1,56 @@ +{{- $name := "blockStaleImages" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Block Stale Images + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.23" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Images that are old usually have some open security vulnerabilities which are not patched. + This policy checks the contents of every container image and inspects them for the create time. + If it finds any image which was built more than 6 months ago this policy blocks the deployment. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: block-stale-images + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Images built more than 6 months ago are prohibited." + foreach: + - list: "request.object.spec.containers" + context: + - name: imageData + imageRegistry: + reference: "{{`{{ element.image }}`}}" + deny: + conditions: + all: + - key: "{{`{{ time_since('', '{{ imageData.configData.created }}', '') }}`}}" + operator: GreaterThan + value: {{ $policyValues.imageAge | default "4380h" }} +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/checkServiceAccount.yaml b/charts/test-chart/templates/other/checkServiceAccount.yaml new file mode 100644 index 0000000..15aec40 --- /dev/null +++ b/charts/test-chart/templates/other/checkServiceAccount.yaml @@ -0,0 +1,52 @@ +{{- $name := "checkServiceAccount" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Check ServiceAccount + policies.kyverno.io/category: {{ $category }}, Sample + policies.kyverno.io/subject: Pod,ServiceAccount + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.21" + policies.kyverno.io/description: >- + ServiceAccounts with privileges to create Pods may be able to do so and name + a ServiceAccount other than the one used to create it. This policy checks the + Pod, if created by a ServiceAccount, and ensures the `serviceAccountName` field + matches the actual ServiceAccount. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-sa + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{`{{serviceAccountName}}`}}" + operator: Equals + value: "*?" + validate: + message: "The ServiceAccount used to create this Pod is confined to using the same account when running the Pod." + pattern: + spec: + serviceAccountName: "{{`{{serviceAccountName}}`}}" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disableAutomountServiceAccountToken.yaml b/charts/test-chart/templates/other/disableAutomountServiceAccountToken.yaml new file mode 100644 index 0000000..ef97ccc --- /dev/null +++ b/charts/test-chart/templates/other/disableAutomountServiceAccountToken.yaml @@ -0,0 +1,71 @@ +{{- $name := "disableAutomountServiceAccountToken" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disable automountServiceAccountToken + policies.kyverno.io/category: {{ $category }}, EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: ServiceAccount + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.21" + policies.kyverno.io/description: >- + A new ServiceAccount called `default` is created whenever a new Namespace is created. + Pods spawned in that Namespace, unless otherwise set, will be assigned this ServiceAccount. + This policy mutates any new `default` ServiceAccounts to disable auto-mounting of the token + into Pods obviating the need to do so individually. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} +#{{- if $policyValues.mutateDefaultServiceAccount }} +# mutateExistingOnPolicyUpdate: true #Mutates already existing matching resources +#{{- end }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-automountserviceaccounttoken + match: + any: + - resources: + kinds: + - ServiceAccount + names: + - default +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: 'automountServiceAccountToken should be set to false for default service account' + pattern: + automountServiceAccountToken: false +#{{- if $policyValues.mutateDefaultServiceAccount }} +# - name: disable-automountserviceaccounttoken +# match: +# any: +# - resources: +# kinds: +# - ServiceAccount +# names: +# - default +#{{- if $policyValues.exclude }} +# exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +#{{- end }} +# mutate: +# targets: # Allows modification of existing resources, permissions for serviceaccounts must be added to Kyverno generatecontrollerExtraResources +# - apiVersion: v1 +# kind: ServiceAccount +# patchStrategicMerge: +# automountServiceAccountToken: false +#{{- end }} +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disablePodAutomountServiceAccountToken.yaml b/charts/test-chart/templates/other/disablePodAutomountServiceAccountToken.yaml new file mode 100644 index 0000000..05954c1 --- /dev/null +++ b/charts/test-chart/templates/other/disablePodAutomountServiceAccountToken.yaml @@ -0,0 +1,52 @@ +{{- $name := "disablePodAutomountServiceAccountToken" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disable automountServiceAccountToken + policies.kyverno.io/category: {{ $category }}, EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.21" + policies.kyverno.io/description: >- + A new ServiceAccount called `default` is created whenever a new Namespace is created. + Pods spawned in that Namespace, unless otherwise set, will be assigned this ServiceAccount. + This policy checks whether automountServiceAccountToken is set to false when serviceAccountName is "default" or not set. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-pod-automountserviceaccounttoken + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{`{{ request.object.spec.serviceAccountName || 'default' }}`}}" + operator: Equals + value: default + validate: + message: 'automountServiceAccountToken should be set to false' + pattern: + spec: + automountServiceAccountToken: false +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disableServiceDiscovery.yaml b/charts/test-chart/templates/other/disableServiceDiscovery.yaml new file mode 100644 index 0000000..dc76bb3 --- /dev/null +++ b/charts/test-chart/templates/other/disableServiceDiscovery.yaml @@ -0,0 +1,48 @@ +{{- $name := "disableServiceDiscovery" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disable Service Discovery + policies.kyverno.io/category: {{ $category }}, EKS Best Practices + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.8.0-rc2 + kyverno.io/kubernetes-version: "1.24" + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/description: >- + Not all Pods require communicating with other Pods or resolving in-cluster Services. + For those, disabling service discovery can increase security as the Pods are limited + to what they can see. This policy checks which Pods set dnsPolicy to `Default` and + enableServiceLinks to `false`, i.e. have service discovery disabled. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-dnspolicy-default + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: 'dnsPolicy should be set to Default and enableServiceLinks should be set to false' + pattern: + spec: + dnsPolicy: Default + enableServiceLinks: false +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disallowAllSecrets.yaml b/charts/test-chart/templates/other/disallowAllSecrets.yaml new file mode 100644 index 0000000..bff4581 --- /dev/null +++ b/charts/test-chart/templates/other/disallowAllSecrets.yaml @@ -0,0 +1,104 @@ +{{- $name := "disallowAllSecrets" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow all Secrets + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod, Secret + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.21" + policies.kyverno.io/description: >- + Secrets often contain sensitive information which not all Pods need consume. + This policy disables the use of all Secrets in a Pod definition. In order to work effectively, + this Policy needs a separate Policy or rule to require `automountServiceAccountToken=false` + at the Pod level or ServiceAccount level since this would otherwise result in a Secret being mounted. + This ClusterPolicy in enforce mode is extraordinarily restrictive. Set .matchPods variable to only validate the policy + for select pods (e.g. only in certain namespaces or with certain names/labels). +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: secrets-not-from-env + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "No Secrets from env." + pattern: + spec: + =(ephemeralContainers): + - name: "*" + =(env): + - =(valueFrom): + X(secretKeyRef): "null" + =(initContainers): + - name: "*" + =(env): + - =(valueFrom): + X(secretKeyRef): "null" + containers: + - name: "*" + =(env): + - =(valueFrom): + X(secretKeyRef): "null" + - name: secrets-not-from-envfrom + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "No Secrets from envFrom." + pattern: + spec: + =(ephemeralContainers): + - name: "*" + =(envFrom): + - X(secretRef): "null" + =(initContainers): + - name: "*" + =(envFrom): + - X(secretRef): "null" + containers: + - name: "*" + =(envFrom): + - X(secretRef): "null" + - name: secrets-not-from-volumes + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "No Secrets from volumes." + pattern: + spec: + =(volumes): + - X(secret): "null" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disallowDefaultNamespace.yaml b/charts/test-chart/templates/other/disallowDefaultNamespace.yaml new file mode 100644 index 0000000..01a0cc7 --- /dev/null +++ b/charts/test-chart/templates/other/disallowDefaultNamespace.yaml @@ -0,0 +1,64 @@ +{{- $name := "disallowDefaultNamespace" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: + pod-policies.kyverno.io/autogen-controllers: none + policies.kyverno.io/title: Disallow Default Namespace + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/category: {{ $category }}, Multi-Tenancy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Kubernetes Namespaces are an optional feature that provide a way to segment and + isolate cluster resources across multiple applications and users. As a best + practice, workloads should be isolated with Namespaces. Namespaces should be required + and the default (empty) Namespace should not be used. This policy validates that Pods + specify a Namespace name other than `default`. Rule auto-generation is disabled here + due to Pod controllers need to specify the `namespace` field under the top-level `metadata` + object and not at the Pod template level. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: validate-namespace + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Using 'default' namespace is not allowed." + pattern: + metadata: + namespace: "!default" + - name: validate-podcontroller-namespace + match: + any: + - resources: + kinds: + - DaemonSet + - Deployment + - Job + - StatefulSet +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Using 'default' namespace is not allowed for pod controllers." + pattern: + metadata: + namespace: "!default" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/disallowEmptyIngressHost.yaml b/charts/test-chart/templates/other/disallowEmptyIngressHost.yaml new file mode 100644 index 0000000..98e9086 --- /dev/null +++ b/charts/test-chart/templates/other/disallowEmptyIngressHost.yaml @@ -0,0 +1,47 @@ +{{- $name := "disallowEmptyIngressHost" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow empty Ingress host + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + An ingress resource needs to define an actual host name + in order to be valid. This policy ensures that there is a + hostname for each rule defined. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: disallow-empty-ingress-host + match: + any: + - resources: + kinds: + - Ingress +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "The Ingress host name must be defined, not empty." + deny: + conditions: + - key: "{{`{{`}} request.object.spec.rules[].host || `[]` | length(@) {{`}}`}}" + operator: NotEquals + value: "{{`{{`}} request.object.spec.rules[].http || `[]` | length(@) {{`}}`}}" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/preventNakedPods.yaml b/charts/test-chart/templates/other/preventNakedPods.yaml new file mode 100644 index 0000000..9ec9514 --- /dev/null +++ b/charts/test-chart/templates/other/preventNakedPods.yaml @@ -0,0 +1,54 @@ +{{- $name := "preventNakedPods" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: + policies.kyverno.io/title: Prevent Naked Pods + pod-policies.kyverno.io/autogen-controllers: none + policies.kyverno.io/category: {{ $category }}, EKS Best Practices + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.7.0 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.23" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Pods not created by workload controllers such as Deployments + have no self-healing or scaling abilities and are unsuitable for production. + This policy prevents such "naked" Pods from being created unless they originate + from a higher-level workload controller of some sort. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: naked-pods + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{`{{request.operation || 'BACKGROUND'}}`}}" + operator: NotEquals + value: DELETE + validate: + message: "Naked Pods are not allowed. They must be created by Pod controllers." + deny: + conditions: + any: + - key: ownerReferences + operator: AnyNotIn + value: "{{`{{request.object.metadata.keys(@)}}`}}" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/protectNodeTaints.yaml b/charts/test-chart/templates/other/protectNodeTaints.yaml new file mode 100644 index 0000000..b935a82 --- /dev/null +++ b/charts/test-chart/templates/other/protectNodeTaints.yaml @@ -0,0 +1,60 @@ +{{- $name := "protectNodeTaints" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Protect Node Taints + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/subject: Node + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/description: >- + Node taints are often used as a control in multi-tenant use cases. + If users can alter them, they may be able to affect scheduling of + Pods which may impact other workloads. This sample prohibits + altering of node taints unless by a user holding the `cluster-admin` + ClusterRole. Use of this policy requires removal of the Node resource filter + in the Kyverno ConfigMap ([Node,*,*]). Due to Kubernetes CVE-2021-25735, this policy + requires, at minimum, one of the following versions of Kubernetes: + v1.18.18, v1.19.10, v1.20.6, or v1.21.0. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: protect-node-taints + match: + any: + - resources: + kinds: + - Node + exclude: + clusterRoles: + - cluster-admin + preconditions: + all: + - key: "{{`{{request.operation || 'BACKGROUND'}}`}}" + operator: Equals + value: UPDATE + validate: + message: "Node taints may not be altered." + deny: + conditions: + any: + - key: "{{`{{request.object.spec.taints}}`}}" + operator: NotEquals + value: "" + - key: "{{`{{request.oldObject.spec.taints}}`}}" + operator: NotEquals + value: "{{`{{request.object.spec.taints}}`}}" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/requireEncryptionAwsLoadBalancers.yaml b/charts/test-chart/templates/other/requireEncryptionAwsLoadBalancers.yaml new file mode 100644 index 0000000..c2a882f --- /dev/null +++ b/charts/test-chart/templates/other/requireEncryptionAwsLoadBalancers.yaml @@ -0,0 +1,51 @@ +{{- $name := "requireEncryptionAwsLoadBalancers" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Require Encryption with AWS LoadBalancers + policies.kyverno.io/category: {{ $category }}, AWS, EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Service + kyverno.io/kyverno-version: 1.7.3, 1.8.0-rc2 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.23-1.24" + policies.kyverno.io/description: >- + Services of type LoadBalancer when deployed inside AWS have support for + transport encryption if it is enabled via an annotation. This policy requires + that Services of type LoadBalancer contain the annotation + service.beta.kubernetes.io/aws-load-balancer-ssl-cert with some value. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: aws-loadbalancer-has-ssl-cert + match: + any: + - resources: + kinds: + - Service +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Service of type LoadBalancer must carry the annotation service.beta.kubernetes.io/aws-load-balancer-ssl-cert." + pattern: + metadata: + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "?*" + (spec): + (type): LoadBalancer +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/requireLabels.yaml b/charts/test-chart/templates/other/requireLabels.yaml new file mode 100644 index 0000000..8ef2853 --- /dev/null +++ b/charts/test-chart/templates/other/requireLabels.yaml @@ -0,0 +1,47 @@ +{{- $name := "requireLabels" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Require Labels + policies.kyverno.io/category: {{ $category }}, Best Practices + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod, Label + policies.kyverno.io/description: >- + Define and use labels that identify semantic attributes of your application or Deployment. + A common set of labels allows tools to work collaboratively, describing objects in a common manner that + all tools can understand. The recommended labels describe applications in a way that can be + queried. .Set requiredLabels as a map of key-value pairs of required labels, and also required label values, + e.g. "app.kubernetes.io/name": "?*" specifies that app.kubernetes.io/name label is required with any value. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-for-labels + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "All labels in .requiredLabels must be set by the Pod." + pattern: + metadata: + labels: {{ toYaml $policyValues.requiredLabels | nindent 14 }} +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/requireRoRootFs.yaml b/charts/test-chart/templates/other/requireRoRootFs.yaml new file mode 100644 index 0000000..b0c9207 --- /dev/null +++ b/charts/test-chart/templates/other/requireRoRootFs.yaml @@ -0,0 +1,49 @@ +{{- $name := "requireRoRootFs" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Require Read-Only Root Filesystem + policies.kyverno.io/category: {{ $category }}, Best Practices, EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/description: >- + A read-only root file system helps to enforce an immutable infrastructure strategy; + the container only needs to write on the mounted volume that persists the state. + An immutable root filesystem can also prevent malicious binaries from writing to the + host system. This policy validates that containers define a securityContext + with `readOnlyRootFilesystem: true`. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: validate-readOnlyRootFilesystem + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Root filesystem must be read-only." + pattern: + spec: + containers: + - securityContext: + readOnlyRootFilesystem: true +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/restrictImageRegistries.yaml b/charts/test-chart/templates/other/restrictImageRegistries.yaml new file mode 100644 index 0000000..0516ec6 --- /dev/null +++ b/charts/test-chart/templates/other/restrictImageRegistries.yaml @@ -0,0 +1,48 @@ +{{- $name := "restrictImageRegistries" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict Image Registries + policies.kyverno.io/category: {{ $category }}, Best Practices, EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Images from unknown, public registries can be of dubious quality and may not be + scanned and secured, representing a high degree of risk. Requiring use of known, approved + registries helps reduce threat exposure by ensuring image pulls only come from them. + Use of this policy requires customization to define your allowable registries. + To allow registries `eu.foo.io` and `bar.io`, set .allowedRegistries to regex pattern "eu.foo.io/* | bar.io/*" +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: validate-registries + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Unknown image registry." + pattern: + spec: + containers: + - image: {{ .allowedRegistries | default "?*" | quote }} +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/restrictIngressWildcard.yaml b/charts/test-chart/templates/other/restrictIngressWildcard.yaml new file mode 100644 index 0000000..b30b67d --- /dev/null +++ b/charts/test-chart/templates/other/restrictIngressWildcard.yaml @@ -0,0 +1,59 @@ +{{- $name := "restrictIngressWildcard" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict Ingress Host with Wildcards + policies.kyverno.io/category: {{ $category }}, Other + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.6.2 + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.23" + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + Ingress hosts optionally accept a wildcard as an alternative + to precise matching. In some cases, this may be too permissive as it + would direct unintended traffic to the given Ingress resource. This + policy enforces that any Ingress host does not contain a wildcard + character. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: block-ingress-wildcard + match: + any: + - resources: + kinds: + - Ingress +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{`{{ request.operation || 'BACKGROUND' }}`}}" + operator: AnyIn + value: ["CREATE", "UPDATE"] + validate: + message: "Wildcards are not permitted as hosts." + foreach: + - list: "request.object.spec.rules[].host" + deny: + conditions: + any: + - key: "{{`{{ contains(element, '*') }}`}}" + operator: Equals + value: true +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/restrictNodePort.yaml b/charts/test-chart/templates/other/restrictNodePort.yaml new file mode 100644 index 0000000..3f0a4df --- /dev/null +++ b/charts/test-chart/templates/other/restrictNodePort.yaml @@ -0,0 +1,47 @@ +{{- $name := "restrictNodePort" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow NodePort + policies.kyverno.io/category: {{ $category }}, Best Practices + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Service + policies.kyverno.io/description: >- + A Kubernetes Service of type NodePort uses a host port to receive traffic from + any source. A NetworkPolicy cannot be used to control traffic to host ports. + Although NodePort Services can be useful, their use must be limited to Services + with additional upstream security checks. This policy validates that any new Services + do not use the `NodePort` type. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: validate-nodeport + match: + any: + - resources: + kinds: + - Service +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "Services of type NodePort are not allowed." + pattern: + spec: + =(type): "!NodePort" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/other/restrictServiceExternalIps.yaml b/charts/test-chart/templates/other/restrictServiceExternalIps.yaml new file mode 100644 index 0000000..ef3e1f8 --- /dev/null +++ b/charts/test-chart/templates/other/restrictServiceExternalIps.yaml @@ -0,0 +1,49 @@ +{{- $name := "restrictServiceExternalIps" }} +{{- $category := "other" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict External IPs + policies.kyverno.io/category: {{ $category }}, Best Practices + policies.kyverno.io/minversion: 1.6.0 + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Service + policies.kyverno.io/description: >- + Service externalIPs can be used for a MITM attack (CVE-2020-8554). + Restrict externalIPs or limit to a known set of addresses. + See: https://github.com/kyverno/kyverno/issues/1367. This policy validates + that the `externalIPs` field is not set on a Service. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-ips + match: + any: + - resources: + kinds: + - Service +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: "externalIPs are not allowed." + pattern: + spec: + # restrict external IP addresses + # you can alternatively restrict to a known set of addresses using: + # =(externalIPs): ["37.10.11.53", "153.10.20.1"] + X(externalIPs): "null" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowHostNamespaces.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowHostNamespaces.yaml index 3c027b3..442057d 100644 --- a/charts/test-chart/templates/podSecurityBaseline/disallowHostNamespaces.yaml +++ b/charts/test-chart/templates/podSecurityBaseline/disallowHostNamespaces.yaml @@ -3,7 +3,7 @@ {{- $policyValues := get .Values.policies $name }} {{- $categoryValues := get .Values.policyCategories $category }} -{{- if and (or $policyValues.enabled $categoryValues.enabled .Values.enableAll) (not (or $policyValues.disabled $categoryValues.disabled)) }} +{{- if include "kyverno-policies.enabled" (list $name $category $) }} apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: @@ -24,16 +24,7 @@ metadata: privileges. Pods should not be allowed access to host namespaces. This policy ensures fields which make use of these host namespaces are unset or set to `false`. spec: - validationFailureAction: {{ coalesce $policyValues.validationFailureAction $categoryValues.validationFailureAction .Values.validationFailureAction }} - validationFailureActionOverrides: {{ toYaml (coalesce $policyValues.validationFailureActionOverrides $categoryValues.validationFailureActionOverrides .Values.validationFailureActionOverrides) | nindent 4 }} -{{- if hasKey $policyValues "background" }} - background: {{ $policyValues.background }} -{{- else if hasKey $categoryValues "background" }} - background: {{ $categoryValues.background }} -{{- else }} - background: {{ .Values.background }} -{{- end }} - failurePolicy: {{ coalesce $policyValues.failurePolicy $categoryValues.failurePolicy .Values.failurePolicy }} +{{ include "kyverno-policies.policySettings" (list $name $category $) }} rules: {{- if $policyValues.rulesOverride }} {{ toYaml $policyValues.rulesOverride | indent 4 }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowHostPath.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowHostPath.yaml new file mode 100644 index 0000000..471cb82 --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/disallowHostPath.yaml @@ -0,0 +1,48 @@ +{{- $name := "disallowHostPath" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow hostPath + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod,Volume + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + HostPath volumes let Pods use host directories and volumes in containers. + Using host resources can be used to access shared data or escalate privileges + and should not be allowed. This policy ensures no hostPath volumes are in use. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: host-path + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset. + pattern: + spec: + =(volumes): + - X(hostPath): "null" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowHostPorts.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowHostPorts.yaml new file mode 100644 index 0000000..0375619 --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/disallowHostPorts.yaml @@ -0,0 +1,57 @@ +{{- $name := "disallowHostPorts" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow hostPorts + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Access to host ports allows potential snooping of network traffic and should not be + allowed, or at minimum restricted to a known list. This policy ensures the `hostPort` + field is unset or set to `0`. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: host-ports-none + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Use of host ports is disallowed. The fields spec.containers[*].ports[*].hostPort + , spec.initContainers[*].ports[*].hostPort, and spec.ephemeralContainers[*].ports[*].hostPort + must either be unset or set to `0`. + pattern: + spec: + =(ephemeralContainers): + - =(ports): + - =(hostPort): 0 + =(initContainers): + - =(ports): + - =(hostPort): 0 + containers: + - =(ports): + - =(hostPort): 0 +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowPrivilegedContainers.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowPrivilegedContainers.yaml new file mode 100644 index 0000000..e09059b --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/disallowPrivilegedContainers.yaml @@ -0,0 +1,55 @@ +{{- $name := "disallowPrivilegedContainers" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow Privileged Containers + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Privileged mode disables most security mechanisms and must not be allowed. This policy + ensures Pods do not call for privileged mode. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: privileged-containers + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Privileged mode is disallowed. The fields spec.containers[*].securityContext.privileged + and spec.initContainers[*].securityContext.privileged must be unset or set to `false`. + pattern: + spec: + =(ephemeralContainers): + - =(securityContext): + =(privileged): "false" + =(initContainers): + - =(securityContext): + =(privileged): "false" + containers: + - =(securityContext): + =(privileged): "false" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowProcMount.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowProcMount.yaml new file mode 100644 index 0000000..a5f1ae4 --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/disallowProcMount.yaml @@ -0,0 +1,59 @@ +{{- $name := "disallowProcMount" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow procMount + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + The default /proc masks are set up to reduce attack surface and should be required. This policy + ensures nothing but the default procMount can be specified. Note that in order for users + to deviate from the `Default` procMount requires setting a feature gate at the API + server. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-proc-mount + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Changing the proc mount from the default is not allowed. The fields + spec.containers[*].securityContext.procMount, spec.initContainers[*].securityContext.procMount, + and spec.ephemeralContainers[*].securityContext.procMount must be unset or + set to `Default`. + pattern: + spec: + =(ephemeralContainers): + - =(securityContext): + =(procMount): "Default" + =(initContainers): + - =(securityContext): + =(procMount): "Default" + containers: + - =(securityContext): + =(procMount): "Default" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/disallowSELinux.yaml b/charts/test-chart/templates/podSecurityBaseline/disallowSELinux.yaml new file mode 100644 index 0000000..8b9db10 --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/disallowSELinux.yaml @@ -0,0 +1,101 @@ +{{- $name := "disallowSELinux" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow SELinux + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + SELinux options can be used to escalate privileges and should not be allowed. This policy + ensures that the `seLinuxOptions` field is undefined. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: selinux-type + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Setting the SELinux type is restricted. The fields + spec.securityContext.seLinuxOptions.type, spec.containers[*].securityContext.seLinuxOptions.type, + , spec.initContainers[*].securityContext.seLinuxOptions, and spec.ephemeralContainers[*].securityContext.seLinuxOptions.type + must either be unset or set to one of the allowed values (container_t, container_init_t, or container_kvm_t). + pattern: + spec: + =(securityContext): + =(seLinuxOptions): + =(type): "container_t | container_init_t | container_kvm_t" + =(ephemeralContainers): + - =(securityContext): + =(seLinuxOptions): + =(type): "container_t | container_init_t | container_kvm_t" + =(initContainers): + - =(securityContext): + =(seLinuxOptions): + =(type): "container_t | container_init_t | container_kvm_t" + containers: + - =(securityContext): + =(seLinuxOptions): + =(type): "container_t | container_init_t | container_kvm_t" + - name: selinux-user-role + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Setting the SELinux user or role is forbidden. The fields + spec.securityContext.seLinuxOptions.user, spec.securityContext.seLinuxOptions.role, + spec.containers[*].securityContext.seLinuxOptions.user, spec.containers[*].securityContext.seLinuxOptions.role, + spec.initContainers[*].securityContext.seLinuxOptions.user, spec.initContainers[*].securityContext.seLinuxOptions.role, + spec.ephemeralContainers[*].securityContext.seLinuxOptions.user, and spec.ephemeralContainers[*].securityContext.seLinuxOptions.role + must be unset. + pattern: + spec: + =(securityContext): + =(seLinuxOptions): + X(user): "null" + X(role): "null" + =(ephemeralContainers): + - =(securityContext): + =(seLinuxOptions): + X(user): "null" + X(role): "null" + =(initContainers): + - =(securityContext): + =(seLinuxOptions): + X(user): "null" + X(role): "null" + containers: + - =(securityContext): + =(seLinuxOptions): + X(user): "null" + X(role): "null" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/restrictAppArmor.yaml b/charts/test-chart/templates/podSecurityBaseline/restrictAppArmor.yaml new file mode 100644 index 0000000..0588112 --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/restrictAppArmor.yaml @@ -0,0 +1,52 @@ +{{- $name := "restrictAppArmor" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict AppArmor + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod, Annotation + policies.kyverno.io/minversion: 1.3.0 + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + On supported hosts, the 'runtime/default' AppArmor profile is applied by default. + The default policy should prevent overriding or disabling the policy, or restrict + overrides to an allowed set of profiles. This policy ensures Pods do not + specify any other AppArmor profiles than `runtime/default` or `localhost/*`. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: app-armor + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Specifying other AppArmor profiles is disallowed. The annotation + `container.apparmor.security.beta.kubernetes.io` if defined + must not be set to anything other than `runtime/default` or `localhost/*`. + pattern: + =(metadata): + =(annotations): + =(container.apparmor.security.beta.kubernetes.io/*): "runtime/default | localhost/*" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityBaseline/restrictSysctls.yaml b/charts/test-chart/templates/podSecurityBaseline/restrictSysctls.yaml new file mode 100644 index 0000000..f8bdcff --- /dev/null +++ b/charts/test-chart/templates/podSecurityBaseline/restrictSysctls.yaml @@ -0,0 +1,56 @@ +{{- $name := "restrictSysctls" }} +{{- $category := "podSecurityBaseline" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict sysctls + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Sysctls can disable security mechanisms or affect all containers on a + host, and should be disallowed except for an allowed "safe" subset. A + sysctl is considered safe if it is namespaced in the container or the + Pod, and it is isolated from other Pods or processes on the same Node. + This policy ensures that only those "safe" subsets can be specified in + a Pod. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-sysctls + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Setting additional sysctls above the allowed type is disallowed. + The field spec.securityContext.sysctls must be unset or not use any other names + than kernel.shm_rmid_forced, net.ipv4.ip_local_port_range, + net.ipv4.ip_unprivileged_port_start, net.ipv4.tcp_syncookies and + net.ipv4.ping_group_range. + pattern: + spec: + =(securityContext): + =(sysctls): + - =(name): "kernel.shm_rmid_forced | net.ipv4.ip_local_port_range | net.ipv4.ip_unprivileged_port_start | net.ipv4.tcp_syncookies | net.ipv4.ping_group_range" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/disallowCapabilitiesStrict.yaml b/charts/test-chart/templates/podSecurityRestricted/disallowCapabilitiesStrict.yaml new file mode 100644 index 0000000..fab3170 --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/disallowCapabilitiesStrict.yaml @@ -0,0 +1,85 @@ +{{- $name := "disallowCapabilitiesStrict" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow Capabilities (Strict) + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Adding capabilities other than `NET_BIND_SERVICE` is disallowed. In addition, + all containers must explicitly drop `ALL` capabilities. Check https://kubernetes.io/docs/concepts/security/pod-security-standards/ + for list of possible capabilities. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: require-drop-all + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{` request.operation || 'BACKGROUND' `}}" + operator: NotEquals + value: DELETE + validate: + message: >- + Containers must drop `ALL` capabilities. + foreach: + - list: request.object.spec.[ephemeralContainers, initContainers, containers][] + deny: + conditions: + all: + - key: ALL + operator: AnyNotIn + value: "{{`{{`}} element.securityContext.capabilities.drop[] || `[]` {{`}}`}}" + - name: adding-capabilities-strict + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + preconditions: + all: + - key: "{{` request.operation || 'BACKGROUND' `}}" + operator: NotEquals + value: DELETE + validate: + message: >- + Any capabilities added other than NET_BIND_SERVICE are disallowed. + foreach: + - list: request.object.spec.[ephemeralContainers, initContainers, containers][] + deny: + conditions: + all: + - key: "{{`{{`}} element.securityContext.capabilities.add[] || `[]` {{`}}`}}" + operator: AnyNotIn + value: + - NET_BIND_SERVICE + - '' +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/disallowPrivilegeEscalation.yaml b/charts/test-chart/templates/podSecurityRestricted/disallowPrivilegeEscalation.yaml new file mode 100644 index 0000000..ee62f44 --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/disallowPrivilegeEscalation.yaml @@ -0,0 +1,58 @@ +{{- $name := "disallowPrivilegeEscalation" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Disallow Privilege Escalation + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Privilege escalation, such as via set-user-ID or set-group-ID file mode, should not be allowed. + This policy ensures the `allowPrivilegeEscalation` field is set to `false`. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: privilege-escalation + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Privilege escalation is disallowed. The fields + spec.containers[*].securityContext.allowPrivilegeEscalation, + spec.initContainers[*].securityContext.allowPrivilegeEscalation, + and spec.ephemeralContainers[*].securityContext.allowPrivilegeEscalation + must be set to `false`. + pattern: + spec: + =(ephemeralContainers): + - securityContext: + allowPrivilegeEscalation: "false" + =(initContainers): + - securityContext: + allowPrivilegeEscalation: "false" + containers: + - securityContext: + allowPrivilegeEscalation: "false" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRoot.yaml b/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRoot.yaml new file mode 100644 index 0000000..bc2a471 --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRoot.yaml @@ -0,0 +1,70 @@ +{{- $name := "requireRunAsNonRoot" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Require runAsNonRoot + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Containers must be required to run as non-root users. This policy ensures + `runAsNonRoot` is set to `true`. A known issue prevents a policy such as this + using `anyPattern` from being persisted properly in Kubernetes 1.23.0-1.23.2. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: run-as-non-root + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Running as root is not allowed. Either the field spec.securityContext.runAsNonRoot + must be set to `true`, or the fields spec.containers[*].securityContext.runAsNonRoot, + spec.initContainers[*].securityContext.runAsNonRoot, and spec.ephemeralContainers[*].securityContext.runAsNonRoot + must be set to `true`. + anyPattern: + - spec: + securityContext: + runAsNonRoot: "true" + =(ephemeralContainers): + - =(securityContext): + =(runAsNonRoot): "true" + =(initContainers): + - =(securityContext): + =(runAsNonRoot): "true" + containers: + - =(securityContext): + =(runAsNonRoot): "true" + - spec: + =(ephemeralContainers): + - securityContext: + runAsNonRoot: "true" + =(initContainers): + - securityContext: + runAsNonRoot: "true" + containers: + - securityContext: + runAsNonRoot: "true" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRootUser.yaml b/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRootUser.yaml new file mode 100644 index 0000000..1ec76a7 --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/requireRunAsNonRootUser.yaml @@ -0,0 +1,59 @@ +{{- $name := "requireRunAsNonRootUser" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Require Run As Non-Root User + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + Containers must be required to run as non-root users. This policy ensures + `runAsUser` is either unset or set to a number greater than zero. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: run-as-non-root-user + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Running as root is not allowed. The fields spec.securityContext.runAsUser, + spec.containers[*].securityContext.runAsUser, spec.initContainers[*].securityContext.runAsUser, + and spec.ephemeralContainers[*].securityContext.runAsUser must be unset or + set to a number greater than zero. + pattern: + spec: + =(securityContext): + =(runAsUser): ">0" + =(ephemeralContainers): + - =(securityContext): + =(runAsUser): ">0" + =(initContainers): + - =(securityContext): + =(runAsUser): ">0" + containers: + - =(securityContext): + =(runAsUser): ">0" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/restrictSeccompStrict.yaml b/charts/test-chart/templates/podSecurityRestricted/restrictSeccompStrict.yaml new file mode 100644 index 0000000..5765466 --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/restrictSeccompStrict.yaml @@ -0,0 +1,81 @@ +{{- $name := "restrictSeccompStrict" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict Seccomp (Strict) + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + kyverno.io/kyverno-version: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + policies.kyverno.io/description: >- + The seccomp profile in the Restricted group must not be explicitly set to Unconfined + but additionally must also not allow an unset value. This policy, + requiring Kubernetes v1.19 or later, ensures that seccomp is + set to `RuntimeDefault` or `Localhost`. A known issue prevents a policy such as this + using `anyPattern` from being persisted properly in Kubernetes 1.23.0-1.23.2. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: check-seccomp-strict + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Use of custom Seccomp profiles is disallowed. The fields + spec.securityContext.seccompProfile.type, + spec.containers[*].securityContext.seccompProfile.type, + spec.initContainers[*].securityContext.seccompProfile.type, and + spec.ephemeralContainers[*].securityContext.seccompProfile.type + must be set to `RuntimeDefault` or `Localhost`. + anyPattern: + - spec: + securityContext: + seccompProfile: + type: "RuntimeDefault | Localhost" + =(ephemeralContainers): + - =(securityContext): + =(seccompProfile): + =(type): "RuntimeDefault | Localhost" + =(initContainers): + - =(securityContext): + =(seccompProfile): + =(type): "RuntimeDefault | Localhost" + containers: + - =(securityContext): + =(seccompProfile): + =(type): "RuntimeDefault | Localhost" + - spec: + =(ephemeralContainers): + - securityContext: + seccompProfile: + type: "RuntimeDefault | Localhost" + =(initContainers): + - securityContext: + seccompProfile: + type: "RuntimeDefault | Localhost" + containers: + - securityContext: + seccompProfile: + type: "RuntimeDefault | Localhost" +{{- end }} +{{- end }} diff --git a/charts/test-chart/templates/podSecurityRestricted/restrictVolumeTypes.yaml b/charts/test-chart/templates/podSecurityRestricted/restrictVolumeTypes.yaml new file mode 100644 index 0000000..6cbdc5e --- /dev/null +++ b/charts/test-chart/templates/podSecurityRestricted/restrictVolumeTypes.yaml @@ -0,0 +1,62 @@ +{{- $name := "restrictVolumeTypes" }} +{{- $category := "podSecurityRestricted" }} +{{- $policyValues := get .Values.policies $name }} +{{- $categoryValues := get .Values.policyCategories $category }} + +{{- if include "kyverno-policies.enabled" (list $name $category $) }} +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: {{ kebabcase $name }} + annotations: +{{- with $policyValues.autogenControllers }} + pod-policies.kyverno.io/autogen-controllers: {{ . }} +{{- end }} + policies.kyverno.io/title: Restrict Volume Types + policies.kyverno.io/category: {{ $category }} + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod,Volume + policies.kyverno.io/minversion: 1.6.0 + kyverno.io/kubernetes-version: "1.22-1.23" + kyverno.io/kyverno-version: 1.6.0 + policies.kyverno.io/description: >- + In addition to restricting HostPath volumes, the restricted pod security profile + limits usage of non-core volume types to those defined through PersistentVolumes. + This policy blocks any other type of volume other than those in the allow list. +spec: +{{ include "kyverno-policies.policySettings" (list $name $category $) }} + rules: +{{- if $policyValues.rulesOverride }} +{{ toYaml $policyValues.rulesOverride | indent 4 }} +{{- else }} + - name: restricted-volumes + match: + any: + - resources: + kinds: + - Pod +{{- if $policyValues.exclude }} + exclude: {{ toYaml $policyValues.exclude | nindent 8 }} +{{- end }} + validate: + message: >- + Only the following types of volumes may be used: configMap, csi, downwardAPI, + emptyDir, ephemeral, persistentVolumeClaim, projected, and secret. + deny: + conditions: + all: + - key: "{{`{{ request.object.spec.volumes[].keys(@)[] || '' }}`}}" + operator: AnyNotIn + value: + - name + - configMap + - csi + - downwardAPI + - emptyDir + - ephemeral + - persistentVolumeClaim + - projected + - secret + - '' +{{- end }} +{{- end }}