diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3eee72305..c417189d2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -408,7 +408,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(block-pod-exec-by-pod-label|block-pod-exec-by-pod-name|block-stale-images|block-updates-deletes|check-env-vars|check-hpa-exists|check-nvidia-gpu|check-serviceaccount|check-serviceaccount-secrets|check-subjectaccessreview|check-vpa-configuration|concatenate-configmaps)$ + tests: ^other$/^(block-pod-exec-by-pod-label|block-pod-exec-by-pod-name|block-stale-images|block-updates-deletes|check-env-vars|check-hpa-exists|check-ingress-nginx-controller-version-and-annotation-policy|check-nvidia-gpu|check-serviceaccount|check-serviceaccount-secrets|check-subjectaccessreview|check-vpa-configuration)$ other-48: strategy: fail-fast: false @@ -425,7 +425,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(copy-namespace-labels|create-default-pdb|create-pod-antiaffinity|deny-commands-in-exec-probe|deny-secret-service-account-token-type|deployment-replicas-higher-than-pdb|disable-automountserviceaccounttoken|disable-service-discovery|disallow-all-secrets|disallow-localhost-services|disallow-secrets-from-env-vars|dns-policy-and-dns-config)$ + tests: ^other$/^(concatenate-configmaps|copy-namespace-labels|create-default-pdb|create-pod-antiaffinity|deny-commands-in-exec-probe|deny-secret-service-account-token-type|deployment-replicas-higher-than-pdb|disable-automountserviceaccounttoken|disable-service-discovery|disallow-all-secrets|disallow-localhost-services|disallow-secrets-from-env-vars)$ other-60: strategy: fail-fast: false @@ -442,7 +442,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(docker-socket-requires-label|enforce-pod-duration|enforce-resources-as-ratio|ensure-probes-different|ensure-production-matches-staging|ensure-readonly-hostpath|exclude-namespaces-dynamically|forbid-cpu-limits|generate-networkpolicy-existing|get-debug-information|imagepullpolicy-always|ingress-host-match-tls)$ + tests: ^other$/^(dns-policy-and-dns-config|docker-socket-requires-label|enforce-pod-duration|enforce-resources-as-ratio|ensure-probes-different|ensure-production-matches-staging|ensure-readonly-hostpath|exclude-namespaces-dynamically|forbid-cpu-limits|generate-networkpolicy-existing|get-debug-information|imagepullpolicy-always)$ other-72: strategy: fail-fast: false @@ -459,7 +459,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(inject-env-var-from-image-label|inject-sidecar-deployment|inspect-csr|kubernetes-version-check|label-existing-namespaces|label-nodes-cri|limit-configmap-for-sa|limit-containers-per-pod|limit-hostpath-type-pv|limit-hostpath-vols|memory-requests-equal-limits|metadata-match-regex)$ + tests: ^other$/^(ingress-host-match-tls|inject-env-var-from-image-label|inject-sidecar-deployment|inspect-csr|kubernetes-version-check|label-existing-namespaces|label-nodes-cri|limit-configmap-for-sa|limit-containers-per-pod|limit-hostpath-type-pv|limit-hostpath-vols|memory-requests-equal-limits)$ other-84: strategy: fail-fast: false @@ -476,7 +476,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(mitigate-log4shell|mutate-large-termination-gps|mutate-pod-binding|namespace-inventory-check|nfs-subdir-external-provisioner-storage-path|only-trustworthy-registries-set-root|pdb-maxunavailable|pdb-maxunavailable-with-deployments|pdb-minavailable|policy-for-exceptions|prepend-image-registry|prevent-bare-pods)$ + tests: ^other$/^(metadata-match-regex|mitigate-log4shell|mutate-large-termination-gps|mutate-pod-binding|namespace-inventory-check|nfs-subdir-external-provisioner-storage-path|only-trustworthy-registries-set-root|pdb-maxunavailable|pdb-maxunavailable-with-deployments|pdb-minavailable|policy-for-exceptions|prepend-image-registry)$ other-96: strategy: fail-fast: false @@ -493,7 +493,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(prevent-cr8escape|prevent-duplicate-hpa|prevent-duplicate-vpa|protect-node-taints|record-creation-details|refresh-env-var-in-pod|refresh-volumes-in-pods|remove-hostpath-volumes|remove-serviceaccount-token|replace-image-registry|replace-image-registry-with-harbor|replace-ingress-hosts)$ + tests: ^other$/^(prevent-bare-pods|prevent-cr8escape|prevent-duplicate-hpa|prevent-duplicate-vpa|protect-node-taints|record-creation-details|refresh-env-var-in-pod|refresh-volumes-in-pods|remove-hostpath-volumes|remove-serviceaccount-token|replace-image-registry|replace-image-registry-with-harbor)$ other-108: strategy: fail-fast: false @@ -510,7 +510,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(require-annotations|require-base-image|require-container-port-names|require-cpu-limits|require-deployments-have-multiple-replicas|require-emptydir-requests-limits|require-image-checksum|require-image-source|require-imagepullsecrets|require-ingress-https|require-netpol|require-non-root-groups)$ + tests: ^other$/^(replace-ingress-hosts|require-annotations|require-base-image|require-container-port-names|require-cpu-limits|require-deployments-have-multiple-replicas|require-emptydir-requests-limits|require-image-checksum|require-image-source|require-imagepullsecrets|require-ingress-https|require-netpol)$ other-120: strategy: fail-fast: false @@ -527,7 +527,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(require-pdb|require-pod-priorityclassname|require-qos-burstable|require-qos-guaranteed|require-reasonable-pdbs|require-replicas-allow-disruption|require-storageclass|require-unique-external-dns|require-unique-service-selector|require-unique-uid-per-workload|resolve-image-to-digest|resource-creation-updating-denied)$ + tests: ^other$/^(require-non-root-groups|require-pdb|require-pod-priorityclassname|require-qos-burstable|require-qos-guaranteed|require-reasonable-pdbs|require-replicas-allow-disruption|require-storageclass|require-unique-external-dns|require-unique-service-selector|require-unique-uid-per-workload|resolve-image-to-digest)$ other-132: strategy: fail-fast: false @@ -544,7 +544,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(restart-deployment-on-secret-change|restrict-annotations|restrict-automount-sa-token|restrict-binding-clusteradmin|restrict-binding-system-groups|restrict-clusterrole-csr|restrict-clusterrole-mutating-validating-admission-webhooks|restrict-clusterrole-nodesproxy|restrict-controlplane-scheduling|restrict-deprecated-registry|restrict-escalation-verbs-roles|restrict-ingress-classes)$ + tests: ^other$/^(resource-creation-updating-denied|restart-deployment-on-secret-change|restrict-annotations|restrict-automount-sa-token|restrict-binding-clusteradmin|restrict-binding-system-groups|restrict-clusterrole-csr|restrict-clusterrole-mutating-validating-admission-webhooks|restrict-clusterrole-nodesproxy|restrict-controlplane-scheduling|restrict-deprecated-registry|restrict-escalation-verbs-roles)$ other-144: strategy: fail-fast: false @@ -561,7 +561,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(restrict-ingress-defaultbackend|restrict-ingress-host|restrict-ingress-wildcard|restrict-jobs|restrict-loadbalancer|restrict-networkpolicy-empty-podselector|restrict-node-affinity|restrict-node-label-changes|restrict-node-label-creation|restrict-node-selection|restrict-pod-controller-serviceaccount-updates|restrict-sa-automount-sa-token)$ + tests: ^other$/^(restrict-ingress-classes|restrict-ingress-defaultbackend|restrict-ingress-host|restrict-ingress-wildcard|restrict-jobs|restrict-loadbalancer|restrict-networkpolicy-empty-podselector|restrict-node-affinity|restrict-node-label-changes|restrict-node-label-creation|restrict-node-selection|restrict-pod-controller-serviceaccount-updates)$ other-156: strategy: fail-fast: false @@ -578,7 +578,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(restrict-secret-role-verbs|restrict-secrets-by-label|restrict-secrets-by-name|restrict-service-port-range|restrict-storageclass|restrict-usergroup-fsgroup-id|restrict-wildcard-resources|restrict-wildcard-verbs|scale-deployment-zero|spread-pods-across-topology|sync-secrets|topologyspreadconstraints-policy)$ + tests: ^other$/^(restrict-sa-automount-sa-token|restrict-secret-role-verbs|restrict-secrets-by-label|restrict-secrets-by-name|restrict-service-port-range|restrict-storageclass|restrict-usergroup-fsgroup-id|restrict-wildcard-resources|restrict-wildcard-verbs|scale-deployment-zero|spread-pods-across-topology|sync-secrets)$ other-168: strategy: fail-fast: false @@ -595,7 +595,7 @@ jobs: - name: Run Tests uses: ./.github/actions/run-tests with: - tests: ^other$/^(unique-ingress-host-and-path|unique-ingress-paths|update-image-tag|verify-vpa-target)$ + tests: ^other$/^(topologyspreadconstraints-policy|unique-ingress-host-and-path|unique-ingress-paths|update-image-tag|verify-vpa-target)$ pod-security_baseline: strategy: fail-fast: false diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/bad-resource.yaml b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/bad-resource.yaml new file mode 100644 index 000000000..ff83224b2 --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/bad-resource.yaml @@ -0,0 +1,36 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: demo + annotations: + nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Safe-Header "Safe Content"; + add_header X-Vuln-Header "Benign\r + HTTP/1.1 200 OK + Content-Type: text/html + + --------"; + return 200 "Original Content"; +spec: + ingressClassName: nginx + rules: + - host: test.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: test-service + port: + number: 80 +--- +apiVersion: v1 +kind: Pod +metadata: + name: ingress-nginx-controller +spec: + containers: + - name: controller + image: registry.k8s.io/ingress-nginx/controller:v1.11.0 diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-step-01-assert-1.yaml b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-step-01-assert-1.yaml new file mode 100644 index 000000000..0c0b87b6d --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-step-01-assert-1.yaml @@ -0,0 +1,10 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-ingress-nginx-controller-version-and-annotation-policy +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready + diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-test.yaml b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-test.yaml new file mode 100644 index 000000000..9953106e4 --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-ingress-nginx-controller-version-and-annotation-policy +spec: + steps: + - name: step-01 + try: + - apply: + file: ../check-ingress-nginx-controller-version-and-annotation-policy.yaml + - name: step-02 + try: + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: check-ingress-nginx-controller-version-and-annotation-policy + spec: + validationFailureAction: Enforce + - assert: + file: chainsaw-step-01-assert-1.yaml + - name: step-03 + try: + - apply: + file: good-resource.yaml + - apply: + expect: + - check: + ($error != null): true + file: bad-resource.yaml diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/good-resource.yaml b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/good-resource.yaml new file mode 100644 index 000000000..07b4c4526 --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/.chainsaw-test/good-resource.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: demo + annotations: + nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" +spec: + ingressClassName: nginx + rules: + - host: test.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: test-service + port: + number: 80 +--- +apiVersion: v1 +kind: Pod +metadata: + name: ingress-nginx-controller-6bbf7f5879-bvh6l +spec: + containers: + - name: controller + image: registry.k8s.io/ingress-nginx/controller:v1.11.2 diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/artifacthub-pkg.yml b/other/check-ingress-nginx-controller-version-and-annotation-policy/artifacthub-pkg.yml new file mode 100644 index 000000000..eb9f68634 --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/artifacthub-pkg.yml @@ -0,0 +1,21 @@ +name: check-ingress-nginx-controller-version-and-annotation-policy +version: 1.0.0 +displayName: Ensure Valid Ingress NGINX Controller and Annotations +createdAt: "2024-08-26T13:14:30Z" +description: >- + This policy ensures that Ingress resources do not have certain disallowed annotations and that the ingress-nginx controller pod is running an appropriate version of the image. It checks for the presence of the `nginx.ingress.kubernetes.io/server-snippet` annotation and disallows its usage, enforces specific values for `auth-tls-verify-client`, and ensures that the ingress-nginx controller image is of the required version. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other/check-ingress-nginx-controller-version-and-annotation-policy/check-ingress-nginx-controller-version-and-annotation-policy.yaml + ``` +keywords: + - kyverno + - Other +readme: | + This policy ensures that Ingress resources do not have certain disallowed annotations and that the ingress-nginx controller pod is running an appropriate version of the image. It checks for the presence of the `nginx.ingress.kubernetes.io/server-snippet` annotation and disallows its usage, enforces specific values for `auth-tls-verify-client`, and ensures that the ingress-nginx controller image is of the required version. + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Other" + kyverno/kubernetesVersion: "1.28" + kyverno/subject: "Deployment,ReplicaSet,StatefulSet,DaemonSet,Ingress" +digest: d4bd973c6d8628e8e8944b3bb1df68997cd39c50f18bdbe98c7df6d3942d96da diff --git a/other/check-ingress-nginx-controller-version-and-annotation-policy/check-ingress-nginx-controller-version-and-annotation-policy.yaml b/other/check-ingress-nginx-controller-version-and-annotation-policy/check-ingress-nginx-controller-version-and-annotation-policy.yaml new file mode 100644 index 000000000..9dba90b99 --- /dev/null +++ b/other/check-ingress-nginx-controller-version-and-annotation-policy/check-ingress-nginx-controller-version-and-annotation-policy.yaml @@ -0,0 +1,87 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-ingress-nginx-controller-version-and-annotation-policy + annotations: + policies.kyverno.io/title: Ensure Valid Ingress NGINX Controller and Annotations + policies.kyverno.io/category: Ingress, Security + policies.kyverno.io/severity: high + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.9.0 + kyverno.io/kubernetes-version: "1.28" + policies.kyverno.io/subject: Ingress, Pod + policies.kyverno.io/description: >- + This policy ensures that Ingress resources do not have certain disallowed annotations and that the ingress-nginx + controller Pod is running an appropriate version of the image. It checks for the presence of the + `nginx.ingress.kubernetes.io/server-snippet` annotation and disallows its usage, enforces specific values + for `auth-tls-verify-client`, and ensures that the ingress-nginx controller image is of the required version. +spec: + validationFailureAction: Audit + background: true + rules: + - name: validate-ingress-annotations + match: + resources: + kinds: + - Ingress + validate: + message: "The annotation nginx.ingress.kubernetes.io/server-snippet is not allowed." + pattern: + metadata: + annotations: + X(nginx.ingress.kubernetes.io/server-snippet): "" + - name: validate-auth-tls-verify-client + match: + resources: + kinds: + - Ingress + validate: + message: "auth-tls-verify-client annotation must be 'on', 'off', 'optional', or 'optional_no_ca'." + deny: + conditions: + any: + - key: "{{request.object.metadata.annotations.\"nginx.ingress.kubernetes.io/auth-tls-verify-client\"}}" + operator: AnyNotIn + value: + - "on" + - "off" + - "optional" + - "optional_no_ca" + - name: ensure-ingress-nginx-controller-version-pattern + match: + resources: + kinds: + - Pod + validate: + message: "The ingress-nginx controller image version must start with v1.11." + pattern: + spec: + containers: + - name: controller + image: "registry.k8s.io/ingress-nginx/controller:v1.11.*" + + - name: deny-lower-ingress-nginx-controller-versions + match: + resources: + kinds: + - Pod + validate: + message: "The ingress-nginx controller image version must be v1.11.2 or greater." + deny: + conditions: + - key: "{{ request.object.spec.containers[?(@.name=='controller')].image }}" + operator: AnyIn + value: + - "registry.k8s.io/ingress-nginx/controller:v1.11.0" + - "registry.k8s.io/ingress-nginx/controller:v1.11.1" + - "registry.k8s.io/ingress-nginx/controller:v1.10.*" + - "registry.k8s.io/ingress-nginx/controller:v1.9.*" + - "registry.k8s.io/ingress-nginx/controller:v1.8.*" + - "registry.k8s.io/ingress-nginx/controller:v1.7.*" + - "registry.k8s.io/ingress-nginx/controller:v1.6.*" + - "registry.k8s.io/ingress-nginx/controller:v1.5.*" + - "registry.k8s.io/ingress-nginx/controller:v1.4.*" + - "registry.k8s.io/ingress-nginx/controller:v1.3.*" + - "registry.k8s.io/ingress-nginx/controller:v1.2.*" + - "registry.k8s.io/ingress-nginx/controller:v1.1.*" + - "registry.k8s.io/ingress-nginx/controller:v1.0.*"