From cd264d90461f8585a86a3a75731e2f007c3fc86c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 4 May 2020 21:03:53 +0200 Subject: [PATCH] enhance conftest - mirror rego --- .drone.yml | 10 ++-- _test/README.md | 5 ++ _test/deprek8/1.16-deprek8ion.rego | 53 +++++++++++++++++++ _test/deprek8/1.17-deprek8ion.rego | 24 +++++++++ _test/deprek8/1.18-deprek8ion.rego | 24 +++++++++ _test/deprek8/1.19-deprek8ion.rego | 31 +++++++++++ _test/deprek8/1.20-deprek8ion.rego | 37 +++++++++++++ _test/deprek8/cert-manager-deprek8ion.rego | 43 +++++++++++++++ _test/deprek8/service-account-deprek8ion.rego | 39 ++++++++++++++ _test/policies/deployment.rego | 13 +++++ 10 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 _test/README.md create mode 100644 _test/deprek8/1.16-deprek8ion.rego create mode 100644 _test/deprek8/1.17-deprek8ion.rego create mode 100644 _test/deprek8/1.18-deprek8ion.rego create mode 100644 _test/deprek8/1.19-deprek8ion.rego create mode 100644 _test/deprek8/1.20-deprek8ion.rego create mode 100644 _test/deprek8/cert-manager-deprek8ion.rego create mode 100644 _test/deprek8/service-account-deprek8ion.rego create mode 100644 _test/policies/deployment.rego diff --git a/.drone.yml b/.drone.yml index da33760..72fa2a7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -2,7 +2,11 @@ kind: pipeline name: conftest steps: -- name: deprek8 - image: quay.io/swade1987/deprek8ion:1.1.9 +- name: policies + image: instrumenta/conftest:latest commands: - - conftest test -p /policies ./ + - conftest test -p ./_test/policies ./ +- name: deprek8 + image: instrumenta/conftest:latest + commands: + - conftest test -p ./_test/deprek8 ./ diff --git a/_test/README.md b/_test/README.md new file mode 100644 index 0000000..8fedfbb --- /dev/null +++ b/_test/README.md @@ -0,0 +1,5 @@ +# Policies + +Sources: +* https://github.com/swade1987/deprek8ion/tree/master/policies +* https://relnotes.k8s.io/?markdown=deprecated diff --git a/_test/deprek8/1.16-deprek8ion.rego b/_test/deprek8/1.16-deprek8ion.rego new file mode 100644 index 0000000..ca0fc3b --- /dev/null +++ b/_test/deprek8/1.16-deprek8ion.rego @@ -0,0 +1,53 @@ +package main + +deny[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _deny with input as obj +} + +deny[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _deny +} + +# Based on https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.16.md + +# All resources under apps/v1beta1 and apps/v1beta2 - use apps/v1 instead +_deny = msg { + apis := ["apps/v1beta1", "apps/v1beta2"] + input.apiVersion == apis[_] + msg := sprintf("%s/%s: API %s has been deprecated, use apps/v1 instead.", [input.kind, input.metadata.name, input.apiVersion]) +} + +# daemonsets, deployments, replicasets resources under extensions/v1beta1 - use apps/v1 instead +_deny = msg { + resources := ["DaemonSet", "Deployment", "ReplicaSet"] + input.apiVersion == "extensions/v1beta1" + input.kind == resources[_] + msg := sprintf("%s/%s: API extensions/v1beta1 for %s has been deprecated, use apps/v1 instead.", [input.kind, input.metadata.name, input.kind]) +} + +# networkpolicies resources under extensions/v1beta1 - use networking.k8s.io/v1 instead +_deny = msg { + input.apiVersion == "extensions/v1beta1" + input.kind == "NetworkPolicy" + msg := sprintf("%s/%s: API extensions/v1beta1 for NetworkPolicy has been deprecated, use networking.k8s.io/v1 instead.", [input.kind, input.metadata.name]) +} + +# podsecuritypolicies resources under extensions/v1beta1 - use policy/v1beta1 instead +_deny = msg { + input.apiVersion == "extensions/v1beta1" + input.kind == "PodSecurityPolicy" + msg := sprintf("%s/%s: API extensions/v1beta1 for PodSecurityPolicy has been deprecated, use policy/v1beta1 instead.", [input.kind, input.metadata.name]) +} + +# PriorityClass resources will no longer be served from scheduling.k8s.io/v1beta1 and scheduling.k8s.io/v1alpha1 in v1.17. +_deny = msg { + apis := ["scheduling.k8s.io/v1beta1", "scheduling.k8s.io/v1alpha1"] + input.apiVersion == apis[_] + input.kind == "PriorityClass" + msg := sprintf("%s/%s: API %s for PriorityClass has been deprecated, use scheduling.k8s.io/v1 instead.", [input.kind, input.metadata.name, input.apiVersion]) +} \ No newline at end of file diff --git a/_test/deprek8/1.17-deprek8ion.rego b/_test/deprek8/1.17-deprek8ion.rego new file mode 100644 index 0000000..7ab5465 --- /dev/null +++ b/_test/deprek8/1.17-deprek8ion.rego @@ -0,0 +1,24 @@ +package main + +deny[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _deny with input as obj +} + +deny[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _deny +} + +# Based on https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.16.md + +# PriorityClass resources will no longer be served from scheduling.k8s.io/v1beta1 and scheduling.k8s.io/v1alpha1 in v1.17. +_deny = msg { + apis := ["scheduling.k8s.io/v1beta1", "scheduling.k8s.io/v1alpha1"] + input.apiVersion == apis[_] + input.kind == "PriorityClass" + msg := sprintf("%s/%s: API %s for PriorityClass has been deprecated, use scheduling.k8s.io/v1 instead.", [input.kind, input.metadata.name, input.apiVersion]) +} \ No newline at end of file diff --git a/_test/deprek8/1.18-deprek8ion.rego b/_test/deprek8/1.18-deprek8ion.rego new file mode 100644 index 0000000..d7ee514 --- /dev/null +++ b/_test/deprek8/1.18-deprek8ion.rego @@ -0,0 +1,24 @@ +package main + +deny[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _deny with input as obj +} + +deny[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _deny +} + +# Based on https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md + +# Within Ingress resources spec.ingressClassName replaces the deprecated kubernetes.io/ingress.class annotation. +_deny = msg { + resources := ["Ingress"] + input.kind == resources[_] + input.metadata.annotations["kubernetes.io/ingress.class"] + msg := sprintf("%s/%s: Ingress annotation kubernetes.io/ingress.class has been deprecated in 1.18, use spec.IngressClassName instead.", [input.kind, input.metadata.name]) +} \ No newline at end of file diff --git a/_test/deprek8/1.19-deprek8ion.rego b/_test/deprek8/1.19-deprek8ion.rego new file mode 100644 index 0000000..b7d0018 --- /dev/null +++ b/_test/deprek8/1.19-deprek8ion.rego @@ -0,0 +1,31 @@ +package main + +warn[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _warn with input as obj +} + +warn[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _warn +} + +# Based on https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.16.md + +# The admissionregistration.k8s.io/v1beta1 versions of MutatingWebhookConfiguration and ValidatingWebhookConfiguration are deprecated in 1.19. Migrate to use admissionregistration.k8s.io/v1 instead +_warn = msg { + kinds := ["MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"] + input.apiVersion == "admissionregistration.k8s.io/v1beta1" + input.kind == kinds[_] + msg := sprintf("%s/%s: API admissionregistration.k8s.io/v1beta1 is deprecated in Kubernetes 1.19, use admissionregistration.k8s.io/v1 instead.", [input.kind, input.metadata.name]) +} + +# The apiextensions.k8s.io/v1beta1 version of CustomResourceDefinition is deprecated in 1.19. Migrate to use apiextensions.k8s.io/v1 instead +_warn = msg { + input.apiVersion == "apiextensions.k8s.io/v1beta1" + input.kind == "CustomResourceDefinition" + msg := sprintf("%s/%s: API apiextensions.k8s.io/v1beta1 for CustomResourceDefinition is deprecated in 1.19, use apiextensions.k8s.io/v1 instead.", [input.kind, input.metadata.name]) +} \ No newline at end of file diff --git a/_test/deprek8/1.20-deprek8ion.rego b/_test/deprek8/1.20-deprek8ion.rego new file mode 100644 index 0000000..19fcbe2 --- /dev/null +++ b/_test/deprek8/1.20-deprek8ion.rego @@ -0,0 +1,37 @@ +package main + +warn[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _warn with input as obj +} + +warn[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _warn +} + +# Based on https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.16.md + +# Ingress resources will no longer be served from extensions/v1beta1 in v1.20. Migrate use to the networking.k8s.io/v1beta1 API, available since v1.14. +_warn = msg { + input.apiVersion == "extensions/v1beta1" + input.kind == "Ingress" + msg := sprintf("%s/%s: API extensions/v1beta1 for Ingress is deprecated from Kubernetes 1.20, use networking.k8s.io/v1beta1 instead.", [input.kind, input.metadata.name]) +} + +# All resources will no longer be served from rbac.authorization.k8s.io/v1alpha1 and rbac.authorization.k8s.io/v1beta1 in 1.20. Migrate to use rbac.authorization.k8s.io/v1 instead +_warn = msg { + apis := ["rbac.authorization.k8s.io/v1alpha1", "rbac.authorization.k8s.io/v1beta1"] + input.apiVersion == apis[_] + msg := sprintf("%s/%s: API %s is deprecated from Kubernetes 1.20, use rbac.authorization.k8s.io/v1 instead.", [input.kind, input.metadata.name, input.apiVersion]) +} + +# Ingress resources will no longer be served from extensions/v1beta1 in v1.20. Migrate use to the networking.k8s.io/v1beta1 API, available since v1.14. +_warn = msg { + input.apiVersion == "extensions/v1beta1" + input.kind == "Ingress" + msg := sprintf("%s/%s: API extensions/v1beta1 for Ingress is deprecated from Kubernetes 1.20, use networking.k8s.io/v1beta1 instead.", [input.kind, input.metadata.name]) +} \ No newline at end of file diff --git a/_test/deprek8/cert-manager-deprek8ion.rego b/_test/deprek8/cert-manager-deprek8ion.rego new file mode 100644 index 0000000..c3eb209 --- /dev/null +++ b/_test/deprek8/cert-manager-deprek8ion.rego @@ -0,0 +1,43 @@ +package main + +deny[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _deny with input as obj +} + +deny[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _deny +} + +warn[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _warn with input as obj +} + +warn[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _warn +} + +# Based on https://github.com/jetstack/cert-manager/releases/tag/v0.11.0 + +_deny = msg { + kinds := ["Certificate", "Issuer", "ClusterIssuer", "CertificateRequest"] + input.apiVersion == "certmanager.k8s.io/v1alpha1" + input.kind == kinds[_] + msg := sprintf("%s/%s: API certmanager.k8s.io/v1alpha1 for %s is obsolete, use cert-manager.io/v1alpha2 instead.", [input.kind, input.metadata.name, input.kind]) +} + +_deny = msg { + kinds := ["Order", "Challenge"] + input.apiVersion == "certmanager.k8s.io/v1alpha1" + input.kind == kinds[_] + msg := sprintf("%s/%s: API certmanager.k8s.io/v1alpha1 for %s is obsolete, use acme.cert-manager.io/v1alpha2 instead.", [input.kind, input.metadata.name, input.kind]) +} \ No newline at end of file diff --git a/_test/deprek8/service-account-deprek8ion.rego b/_test/deprek8/service-account-deprek8ion.rego new file mode 100644 index 0000000..2485b8c --- /dev/null +++ b/_test/deprek8/service-account-deprek8ion.rego @@ -0,0 +1,39 @@ +package main + +warn[msg] { + input.apiVersion == "v1" + input.kind == "List" + obj := input.items[_] + msg := _warn with input as obj +} + +warn[msg] { + input.apiVersion != "v1" + input.kind != "List" + msg := _warn +} + +# Based on https://github.com/kubernetes/kubernetes/issues/47198 +# Warn about the deprecated serviceAccount field in podSpec. + +_warn = msg { + resources := ["Pod"] + input.kind == resources[_] + input.spec.serviceAccount + msg := sprintf("%s/%s: The serviceAccount field in the podSpec will be deprecated soon, use serviceAccountName instead.", [input.kind, input.metadata.name]) +} + +_warn = msg { + resources := ["CronJob"] + input.kind == resources[_] + input.spec.jobTemplate.spec.template.spec.serviceAccount + msg := sprintf("%s/%s: The serviceAccount field in the podSpec will be deprecated soon, use serviceAccountName instead.", [input.kind, input.metadata.name]) +} + +_warn = msg { + resources := ["Deployment", "DaemonSet", "Job", "ReplicaSet", "ReplicationController", "StatefulSet"] + input.kind == resources[_] + input.spec.template.spec.serviceAccount + msg := sprintf("%s/%s: The serviceAccount field in the podSpec will be deprecated soon, use serviceAccountName instead.", [input.kind, input.metadata.name]) +} + diff --git a/_test/policies/deployment.rego b/_test/policies/deployment.rego new file mode 100644 index 0000000..024424b --- /dev/null +++ b/_test/policies/deployment.rego @@ -0,0 +1,13 @@ +package main + +deny[msg] { + input.kind = "Deployment" + not input.spec.template.spec.securityContext.runAsNonRoot = true + msg = "Containers must not run as root" +} + +deny[msg] { + input.kind = "Deployment" + not input.spec.selector.matchLabels.app + msg = "Containers must provide app label for pod selectors" +}