diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 4e5b5bab5..7be61f658 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -114,7 +114,7 @@ jobs: make require-suites require_sync: runs-on: ubuntu-latest - name: "Require a sync.yaml file and metadata.gatekeeper.sh/requiresSyncData annotation for every template.yaml using data.inventory" + name: "Require a sync.yaml file and metadata.gatekeeper.sh/requires-sync-data annotation for every template.yaml using data.inventory" steps: - name: Harden Runner uses: step-security/harden-runner@128a63446a954579617e875aaab7d2978154e969 # v2.4.0 diff --git a/Makefile b/Makefile index 9485dbc0f..08e489ecd 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ generate-website-docs: unit-test: cd $(ARTIFACTHUB_SCRIPT_DIR); go test -v cd $(VALIDATE_SCRIPT_DIR); go test -v + cd $(REQUIRE_SYNC_SCRIPT_DIR); go test -v .PHONY: generate-artifacthub-artifacts generate-artifacthub-artifacts: diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/artifacthub-pkg.yml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/artifacthub-pkg.yml new file mode 100644 index 000000000..86b025e9f --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.0.1 +name: k8shorizontalpodautoscaler +displayName: Horizontal Pod Autoscaler +createdAt: "2023-06-12T20:47:46Z" +description: Disallow the following scenarios when deploying `HorizontalPodAutoscalers` 1. Deployment of HorizontalPodAutoscalers with `.spec.minReplicas` or `.spec.maxReplicas` outside the ranges defined in the constraint 2. Deployment of HorizontalPodAutoscalers where the difference between `.spec.minReplicas` and `.spec.maxReplicas` is less than the configured `minimumReplicaSpread` 3. Deployment of HorizontalPodAutoscalers that do not reference a valid `scaleTargetRef` (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet). +digest: 6ad69d08a3b11e856a1366f8dcdb370ca05ab83d8278d0e0df9698fd8b973e72 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/horizontalpodautoscaler +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Horizontal Pod Autoscaler + Disallow the following scenarios when deploying `HorizontalPodAutoscalers` 1. Deployment of HorizontalPodAutoscalers with `.spec.minReplicas` or `.spec.maxReplicas` outside the ranges defined in the constraint 2. Deployment of HorizontalPodAutoscalers where the difference between `.spec.minReplicas` and `.spec.maxReplicas` is less than the configured `minimumReplicaSpread` 3. Deployment of HorizontalPodAutoscalers that do not reference a valid `scaleTargetRef` (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet). +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/horizontalpodautoscaler/1.0.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/kustomization.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/constraint.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/constraint.yaml new file mode 100644 index 000000000..80d2c9a93 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/constraint.yaml @@ -0,0 +1,16 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sHorizontalPodAutoscaler +metadata: + name: horizontal-pod-autoscaler +spec: + enforcementAction: deny + match: + kinds: + - apiGroups: ["autoscaling"] + kinds: ["HorizontalPodAutoscaler"] + parameters: + minimumReplicaSpread: 1 + enforceScaleTargetRef: true + ranges: + - min_replicas: 3 + max_replicas: 6 diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_allowed_hpa.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_allowed_hpa.yaml new file mode 100644 index 000000000..5c0f0dc42 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_allowed_hpa.yaml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: nginx-hpa-allowed + namespace: default +spec: + minReplicas: 3 + maxReplicas: 6 + metrics: + - resource: + name: cpu + target: + averageUtilization: 900 + type: Utilization + type: Resource + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: nginx-deployment diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicas.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicas.yaml new file mode 100644 index 000000000..e7b8a984b --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicas.yaml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: nginx-hpa-disallowed-replicas + namespace: default +spec: + minReplicas: 2 + maxReplicas: 7 + metrics: + - resource: + name: cpu + target: + averageUtilization: 900 + type: Utilization + type: Resource + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: nginx-deployment diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicaspread.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicaspread.yaml new file mode 100644 index 000000000..ee915d1ba --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_replicaspread.yaml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: nginx-hpa-disallowed-replicaspread + namespace: default +spec: + minReplicas: 4 + maxReplicas: 4 + metrics: + - resource: + name: cpu + target: + averageUtilization: 900 + type: Utilization + type: Resource + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: nginx-deployment diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_scaletarget.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_scaletarget.yaml new file mode 100644 index 000000000..4c390f674 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_disallowed_hpa_scaletarget.yaml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: nginx-hpa-disallowed-scaletarget + namespace: default +spec: + minReplicas: 3 + maxReplicas: 6 + metrics: + - resource: + name: cpu + target: + averageUtilization: 900 + type: Utilization + type: Resource + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: nginx-deployment-missing diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_inventory.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_inventory.yaml new file mode 100644 index 000000000..507103931 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/samples/horizontalpodautoscaler/example_inventory.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + namespace: default + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + example: allowed-deployment + template: + metadata: + labels: + app: nginx + example: allowed-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/suite.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/suite.yaml new file mode 100644 index 000000000..1500708b0 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/suite.yaml @@ -0,0 +1,33 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: horizontalpodautoscaler +tests: +- name: horizontal-pod-autoscaler + template: template.yaml + constraint: samples/horizontalpodautoscaler/constraint.yaml + cases: + - name: example-allowed-hpa + object: samples/horizontalpodautoscaler/example_allowed_hpa.yaml + inventory: + - samples/horizontalpodautoscaler/example_inventory.yaml + assertions: + - violations: no + - name: example-disallowed-hpa-replicas + object: samples/horizontalpodautoscaler/example_disallowed_hpa_replicas.yaml + inventory: + - samples/horizontalpodautoscaler/example_inventory.yaml + assertions: + - violations: yes + - name: example-disallowed-hpa-replicaspread + object: samples/horizontalpodautoscaler/example_disallowed_hpa_replicaspread.yaml + inventory: + - samples/horizontalpodautoscaler/example_inventory.yaml + assertions: + - violations: yes + - name: example-disallowed-scaletarget + object: samples/horizontalpodautoscaler/example_disallowed_hpa_scaletarget.yaml + inventory: + - samples/horizontalpodautoscaler/example_inventory.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/sync.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/sync.yaml new file mode 100644 index 000000000..abfbe2169 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/sync.yaml @@ -0,0 +1,14 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "apps" + version: "v1" + kind: "Deployment" + - group: "apps" + version: "v1" + kind: "StatefulSet" diff --git a/artifacthub/library/general/horizontalpodautoscaler/1.0.1/template.yaml b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/template.yaml new file mode 100644 index 000000000..3e43f28a7 --- /dev/null +++ b/artifacthub/library/general/horizontalpodautoscaler/1.0.1/template.yaml @@ -0,0 +1,102 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8shorizontalpodautoscaler + annotations: + metadata.gatekeeper.sh/title: "Horizontal Pod Autoscaler" + metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups":["apps"], + "versions": ["v1"], + "kinds": ["Deployment"] + }, + { + "groups":["apps"], + "versions": ["v1"], + "kinds": ["StatefulSet"] + } + ] + ]" + description: >- + Disallow the following scenarios when deploying `HorizontalPodAutoscalers` + 1. Deployment of HorizontalPodAutoscalers with `.spec.minReplicas` or `.spec.maxReplicas` outside the ranges defined in the constraint + 2. Deployment of HorizontalPodAutoscalers where the difference between `.spec.minReplicas` and `.spec.maxReplicas` is less than the configured `minimumReplicaSpread` + 3. Deployment of HorizontalPodAutoscalers that do not reference a valid `scaleTargetRef` (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet). +spec: + crd: + spec: + names: + kind: K8sHorizontalPodAutoscaler + validation: + # Schema for the `parameters` field + openAPIV3Schema: + type: object + properties: + enforceScaleTargetRef: + description: If set to true it validates the HPA scaleTargetRef exists + type: boolean + minimumReplicaSpread: + description: If configured it enforces the minReplicas and maxReplicas in an HPA must have a spread of at least this many replicas + type: integer + ranges: + type: array + description: Allowed ranges for numbers of replicas. Values are inclusive. + items: + type: object + description: A range of allowed replicas. Values are inclusive. + properties: + min_replicas: + description: The minimum number of replicas allowed, inclusive. + type: integer + max_replicas: + description: The maximum number of replicas allowed, inclusive. + type: integer + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8shorizontalpodautoscaler + + violation[{"msg": msg}] { + input.review.kind.kind == "HorizontalPodAutoscaler" + hpa := input.review.object + + not input_replica_limit(hpa) + msg := sprintf("The %v <%v> minReplicas %v or maxReplicas %v is not allowed: %v. Allowed ranges: %v", [hpa.kind, hpa.metadata.name, hpa.spec.minReplicas, hpa.spec.maxReplicas, input.parameters.ranges]) + } + + violation[{"msg": msg}] { + input.review.kind.kind == "HorizontalPodAutoscaler" + hpa := input.review.object + + not input_replica_spread(hpa) + + msg := sprintf("The %v <%v> is configured with minReplicas %v and maxReplicas %v which is a spread of %v replica(s). The spread must be at least %v replica(s)", [hpa.kind, hpa.metadata.name, hpa.spec.minReplicas, hpa.spec.maxReplicas, hpa.spec.maxReplicas - hpa.spec.minReplicas, input.parameters.minimumReplicaSpread]) + } + + violation[{"msg": msg}] { + input.review.kind.kind == "HorizontalPodAutoscaler" + hpa := input.review.object + input.parameters.enforceScaleTargetRef + + not data.inventory.namespace[hpa.metadata.namespace][hpa.spec.scaleTargetRef.apiVersion][hpa.spec.scaleTargetRef.kind][hpa.spec.scaleTargetRef.name] + msg := sprintf("The HorizontalPodAutoscaler <%v> has a scaleTargetRef of <%v/%v> but it does not exist. The scaleTargetRef for the HorizontalPodAutoscaler must exist", [hpa.metadata.name, hpa.spec.scaleTargetRef.kind, hpa.spec.scaleTargetRef.name]) + } + + input_replica_limit(hpa) { + count(input.parameters.ranges) > 0 + range := input.parameters.ranges[_] + value_within_range(range, hpa.spec.minReplicas, hpa.spec.maxReplicas) + } + + value_within_range(range, min_provided, max_provided) { + range.min_replicas <= min_provided + range.max_replicas >= max_provided + } + + input_replica_spread(hpa) { + input.parameters.minimumReplicaSpread + (hpa.spec.maxReplicas - hpa.spec.minReplicas) >= input.parameters.minimumReplicaSpread + } diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/artifacthub-pkg.yml b/artifacthub/library/general/poddisruptionbudget/1.0.3/artifacthub-pkg.yml new file mode 100644 index 000000000..0cadd4147 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.3 +name: k8spoddisruptionbudget +displayName: Pod Disruption Budget +createdAt: "2023-06-12T20:47:47Z" +description: |- + Disallow the following scenarios when deploying PodDisruptionBudgets or resources that implement the replica subresource (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet): 1. Deployment of PodDisruptionBudgets with .spec.maxUnavailable == 0 2. Deployment of PodDisruptionBudgets with .spec.minAvailable == .spec.replicas of the resource with replica subresource This will prevent PodDisruptionBudgets from blocking voluntary disruptions such as node draining. + https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +digest: b5f0b45b6b1894cf43f6b40970557afb9549b6541760c9481bc8acfc3c572815 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/poddisruptionbudget +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Pod Disruption Budget + Disallow the following scenarios when deploying PodDisruptionBudgets or resources that implement the replica subresource (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet): 1. Deployment of PodDisruptionBudgets with .spec.maxUnavailable == 0 2. Deployment of PodDisruptionBudgets with .spec.minAvailable == .spec.replicas of the resource with replica subresource This will prevent PodDisruptionBudgets from blocking voluntary disruptions such as node draining. + https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/poddisruptionbudget/1.0.3/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/kustomization.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/constraint.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/constraint.yaml new file mode 100644 index 000000000..c689a6d41 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sPodDisruptionBudget +metadata: + name: pod-distruption-budget +spec: + match: + kinds: + - apiGroups: ["apps"] + kinds: ["Deployment", "ReplicaSet", "StatefulSet"] + - apiGroups: ["policy"] + kinds: ["PodDisruptionBudget"] + - apiGroups: [""] + kinds: ["ReplicationController"] diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment1.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment1.yaml new file mode 100644 index 000000000..6b70a8932 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment1.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-allowed-1 + namespace: default + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + example: allowed-deployment-1 + template: + metadata: + labels: + app: nginx + example: allowed-deployment-1 + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment2.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment2.yaml new file mode 100644 index 000000000..ae96d99a9 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment2.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-allowed-2 + namespace: default + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + example: allowed-deployment-2 + template: + metadata: + labels: + app: nginx + example: allowed-deployment-2 + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment3.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment3.yaml new file mode 100644 index 000000000..154f44484 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment3.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-allowed-3 + namespace: default + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + example: allowed-deployment-3 + template: + metadata: + labels: + app: nginx + example: allowed-deployment-3 + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment4.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment4.yaml new file mode 100644 index 000000000..7c2d2e8ed --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_deployment4.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-allowed-4 + namespace: default + labels: + app: non-matching-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: non-matching-nginx + example: allowed-deployment-4 + template: + metadata: + labels: + app: non-matching-nginx + example: allowed-deployment-4 + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_pdb.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_pdb.yaml new file mode 100644 index 000000000..f860777fb --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_allowed_pdb.yaml @@ -0,0 +1,10 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: nginx-pdb-allowed + namespace: default +spec: + maxUnavailable: 1 + selector: + matchLabels: + foo: bar diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_deployment.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_deployment.yaml new file mode 100644 index 000000000..76044a6c9 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-disallowed + namespace: default + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + example: disallowed-deployment + template: + metadata: + labels: + app: nginx + example: disallowed-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_pdb.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_pdb.yaml new file mode 100644 index 000000000..41d0b9162 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_disallowed_pdb.yaml @@ -0,0 +1,10 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: nginx-pdb-disallowed + namespace: default +spec: + maxUnavailable: 0 + selector: + matchLabels: + foo: bar diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed1.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed1.yaml new file mode 100644 index 000000000..df1cd233e --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed1.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: inventory-nginx-pdb-allowed-1 + namespace: default +spec: + minAvailable: 2 + selector: + matchLabels: + app: nginx + example: allowed-deployment-1 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed2.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed2.yaml new file mode 100644 index 000000000..e4ccb63be --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed2.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: inventory-nginx-pdb-allowed-2 + namespace: default +spec: + maxUnavailable: 1 + selector: + matchLabels: + app: nginx + example: allowed-deployment-2 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed3.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed3.yaml new file mode 100644 index 000000000..18a0eeb47 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed3.yaml @@ -0,0 +1,10 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: inventory-nginx-pdb-allowed-3 + namespace: default +spec: + minAvailable: 2 + selector: + matchLabels: + app: nginx diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed4.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed4.yaml new file mode 100644 index 000000000..90f150163 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_allowed4.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: inventory-mongo-pdb-allowed-3 + namespace: default +spec: + minAvailable: 2 + selector: + matchLabels: + app: mongo + example: non-matching-deployment-3 diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_disallowed.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_disallowed.yaml new file mode 100644 index 000000000..a35c58b48 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/samples/poddisruptionbudget/example_inventory_disallowed.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: inventory-nginx-pdb-disallowed + namespace: default +spec: + minAvailable: 3 + selector: + matchLabels: + app: nginx + example: disallowed-deployment diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/suite.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/suite.yaml new file mode 100644 index 000000000..0e30d6b35 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/suite.yaml @@ -0,0 +1,47 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: poddisruptionbudget +tests: +- name: pod-disruption-budget + template: template.yaml + constraint: samples/poddisruptionbudget/constraint.yaml + cases: + - name: example-allowed-pdb + object: samples/poddisruptionbudget/example_allowed_pdb.yaml + assertions: + - violations: no + - name: example-disallowed-pdb + object: samples/poddisruptionbudget/example_disallowed_pdb.yaml + assertions: + - violations: yes + - name: example-allowed-min-available + object: samples/poddisruptionbudget/example_allowed_deployment1.yaml + inventory: + - samples/poddisruptionbudget/example_inventory_allowed1.yaml + assertions: + - violations: no + - name: example-allowed-max-unavailable + object: samples/poddisruptionbudget/example_allowed_deployment2.yaml + inventory: + - samples/poddisruptionbudget/example_inventory_allowed2.yaml + assertions: + - violations: no + - name: example-allowed-subset-selector + object: samples/poddisruptionbudget/example_allowed_deployment3.yaml + inventory: + - samples/poddisruptionbudget/example_inventory_allowed3.yaml + assertions: + - violations: no + - name: example-allowed-nomatch-selector + object: samples/poddisruptionbudget/example_allowed_deployment4.yaml + inventory: + - samples/poddisruptionbudget/example_inventory_allowed4.yaml + assertions: + - violations: no + - name: example-disallowed-min-available + object: samples/poddisruptionbudget/example_disallowed_deployment.yaml + inventory: + - samples/poddisruptionbudget/example_inventory_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/sync.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/sync.yaml new file mode 100644 index 000000000..0977d2904 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/sync.yaml @@ -0,0 +1,11 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "policy" + version: "v1" + kind: "PodDisruptionBudget" diff --git a/artifacthub/library/general/poddisruptionbudget/1.0.3/template.yaml b/artifacthub/library/general/poddisruptionbudget/1.0.3/template.yaml new file mode 100644 index 000000000..d44000824 --- /dev/null +++ b/artifacthub/library/general/poddisruptionbudget/1.0.3/template.yaml @@ -0,0 +1,90 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8spoddisruptionbudget + annotations: + metadata.gatekeeper.sh/title: "Pod Disruption Budget" + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups":["policy"], + "versions": ["v1"], + "kinds": ["PodDisruptionBudget"] + } + ] + ]" + description: >- + Disallow the following scenarios when deploying PodDisruptionBudgets or resources that implement the replica subresource (e.g. Deployment, ReplicationController, ReplicaSet, StatefulSet): + 1. Deployment of PodDisruptionBudgets with .spec.maxUnavailable == 0 + 2. Deployment of PodDisruptionBudgets with .spec.minAvailable == .spec.replicas of the resource with replica subresource + This will prevent PodDisruptionBudgets from blocking voluntary disruptions such as node draining. + + https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +spec: + crd: + spec: + names: + kind: K8sPodDisruptionBudget + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8spoddisruptionbudget + + violation[{"msg": msg}] { + input.review.kind.kind == "PodDisruptionBudget" + pdb := input.review.object + + not valid_pdb_max_unavailable(pdb) + msg := sprintf( + "PodDisruptionBudget <%v> has maxUnavailable of 0, only positive integers are allowed for maxUnavailable", + [pdb.metadata.name], + ) + } + + violation[{"msg": msg}] { + obj := input.review.object + pdb := data.inventory.namespace[obj.metadata.namespace]["policy/v1"].PodDisruptionBudget[_] + + matchLabels := { [label, value] | some label; value := pdb.spec.selector.matchLabels[label] } + labels := { [label, value] | some label; value := obj.spec.selector.matchLabels[label] } + count(matchLabels - labels) == 0 + + not valid_pdb_max_unavailable(pdb) + msg := sprintf( + "%v <%v> has been selected by PodDisruptionBudget <%v> but has maxUnavailable of 0, only positive integers are allowed for maxUnavailable", + [obj.kind, obj.metadata.name, pdb.metadata.name], + ) + } + + violation[{"msg": msg}] { + obj := input.review.object + pdb := data.inventory.namespace[obj.metadata.namespace]["policy/v1"].PodDisruptionBudget[_] + + matchLabels := { [label, value] | some label; value := pdb.spec.selector.matchLabels[label] } + labels := { [label, value] | some label; value := obj.spec.selector.matchLabels[label] } + count(matchLabels - labels) == 0 + + not valid_pdb_min_available(obj, pdb) + msg := sprintf( + "%v <%v> has %v replica(s) but PodDisruptionBudget <%v> has minAvailable of %v, PodDisruptionBudget count should always be lower than replica(s), and not used when replica(s) is set to 1", + [obj.kind, obj.metadata.name, obj.spec.replicas, pdb.metadata.name, pdb.spec.minAvailable], + ) + } + + valid_pdb_min_available(obj, pdb) { + # default to -1 if minAvailable is not set so valid_pdb_min_available is always true + # for objects with >= 0 replicas. If minAvailable defaults to >= 0, objects with + # replicas field might violate this constraint if they are equal to the default set here + min_available := object.get(pdb.spec, "minAvailable", -1) + obj.spec.replicas > min_available + } + + valid_pdb_max_unavailable(pdb) { + # default to 1 if maxUnavailable is not set so valid_pdb_max_unavailable always returns true. + # If maxUnavailable defaults to 0, it violates this constraint because all pods needs to be + # available and no pods can be evicted voluntarily + max_unavailable := object.get(pdb.spec, "maxUnavailable", 1) + max_unavailable > 0 + } diff --git a/artifacthub/library/general/storageclass/1.1.1/README.md b/artifacthub/library/general/storageclass/1.1.1/README.md new file mode 100644 index 000000000..f398931a9 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/README.md @@ -0,0 +1,17 @@ +# StorageClass + +The `StorageClass` constraint blocks the creation of PVCs or StatefulSets +where the specified storage class doesn't exist on the cluster, or that no +storage class at all is specified. + +This policy helps prevent workloads from getting stuck indefinitely waiting +for a storage class to provision the persistent storage that will never +happen. This often causes users to get confused as to why their pods are stuck +pending, and requires deleting the StatefulSet and any PVCs it has created along +with redeploying the workload in order to fix. Blocking it up front makes it +much easier to fix before there is a mess to clean up. + +Optionally accepts an `allowedStorageClasses` parameter to restrict PVCs and +StatefulSets to a subset list of allowed storage classes. + +> Please note that this policy requires Gatekeeper v3.9.0 or later. diff --git a/artifacthub/library/general/storageclass/1.1.1/artifacthub-pkg.yml b/artifacthub/library/general/storageclass/1.1.1/artifacthub-pkg.yml new file mode 100644 index 000000000..ded49fa15 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/artifacthub-pkg.yml @@ -0,0 +1,22 @@ +version: 1.1.1 +name: k8sstorageclass +displayName: Storage Class +createdAt: "2023-06-12T20:47:48Z" +description: Requires storage classes to be specified when used. Only Gatekeeper 3.9+ is supported. +digest: ebe3175effd0c3b2850bc0bce4b1abe02f33329455431e07b807a5d9d87674c2 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/storageclass +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Storage Class + Requires storage classes to be specified when used. Only Gatekeeper 3.9+ is supported. +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/storageclass/1.1.1/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/storageclass/1.1.1/kustomization.yaml b/artifacthub/library/general/storageclass/1.1.1/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/constraint.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/constraint.yaml new file mode 100644 index 000000000..ddd6acaa5 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/constraint.yaml @@ -0,0 +1,15 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sStorageClass +metadata: + name: allowed-storageclass +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["PersistentVolumeClaim"] + - apiGroups: ["apps"] + kinds: ["StatefulSet"] + parameters: + includeStorageClassesInMessage: true + allowedStorageClasses: + - allowed-storage-class diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_allowed.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_allowed.yaml new file mode 100644 index 000000000..7982eca54 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_allowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: allowed-storage-class-pvc +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: allowed-storage-class diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_disallowed.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_disallowed.yaml new file mode 100644 index 000000000..7f679bb30 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_disallowed.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: disallowed-storage-class-pvc +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: disallowed-storage-class diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_inventory_allowed_storageclass.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_inventory_allowed_storageclass.yaml new file mode 100644 index 000000000..930822f4a --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass-allowlist/example_inventory_allowed_storageclass.yaml @@ -0,0 +1,7 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: allowed-storage-class +provisioner: foo +parameters: +allowVolumeExpansion: true diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/constraint.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/constraint.yaml new file mode 100644 index 000000000..6b49e5dad --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/constraint.yaml @@ -0,0 +1,13 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sStorageClass +metadata: + name: storageclass +spec: + match: + kinds: + - apiGroups: [""] + kinds: ["PersistentVolumeClaim"] + - apiGroups: ["apps"] + kinds: ["StatefulSet"] + parameters: + includeStorageClassesInMessage: true diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_pvc.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_pvc.yaml new file mode 100644 index 000000000..a8608f53e --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ok +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: somestorageclass diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_ss.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_ss.yaml new file mode 100644 index 000000000..b1bd5db79 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_allowed_ss.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: volumeclaimstorageclass +spec: + selector: + matchLabels: + app: volumeclaimstorageclass + serviceName: volumeclaimstorageclass + replicas: 1 + template: + metadata: + labels: + app: volumeclaimstorageclass + spec: + containers: + - name: main + image: registry.k8s.io/nginx-slim:0.8 + volumeMounts: + - name: data + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: "somestorageclass" + resources: + requests: + storage: 1Gi diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_badname.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_badname.yaml new file mode 100644 index 000000000..ec75200c4 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_badname.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: badstorageclass +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: badstorageclass diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_nonamename.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_nonamename.yaml new file mode 100644 index 000000000..2f9cc12ec --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_pvc_nonamename.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: nostorageclass +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_badnamename.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_badnamename.yaml new file mode 100644 index 000000000..58c98fd7d --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_badnamename.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: badvolumeclaimstorageclass +spec: + selector: + matchLabels: + app: badvolumeclaimstorageclass + serviceName: badvolumeclaimstorageclass + replicas: 1 + template: + metadata: + labels: + app: badvolumeclaimstorageclass + spec: + containers: + - name: main + image: registry.k8s.io/nginx-slim:0.8 + volumeMounts: + - name: data + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: "badstorageclass" + resources: + requests: + storage: 1Gi diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_nonamename.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_nonamename.yaml new file mode 100644 index 000000000..ece7c23dd --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_disallowed_ssvct_nonamename.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: novolumeclaimstorageclass +spec: + selector: + matchLabels: + app: novolumeclaimstorageclass + serviceName: novolumeclaimstorageclass + replicas: 1 + template: + metadata: + labels: + app: novolumeclaimstorageclass + spec: + containers: + - name: main + image: registry.k8s.io/nginx-slim:0.8 + volumeMounts: + - name: data + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_inventory_allowed_storageclass.yaml b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_inventory_allowed_storageclass.yaml new file mode 100644 index 000000000..0cdee0aa3 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/samples/storageclass/example_inventory_allowed_storageclass.yaml @@ -0,0 +1,7 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: somestorageclass +provisioner: foo +parameters: +allowVolumeExpansion: true diff --git a/artifacthub/library/general/storageclass/1.1.1/suite.yaml b/artifacthub/library/general/storageclass/1.1.1/suite.yaml new file mode 100644 index 000000000..9cccc2ebb --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/suite.yaml @@ -0,0 +1,53 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: storageclass +tests: +- name: storageclass + template: template.yaml + constraint: samples/storageclass/constraint.yaml + cases: + - name: example-allowed-pvc + object: samples/storageclass/example_allowed_pvc.yaml + inventory: + - samples/storageclass/example_inventory_allowed_storageclass.yaml + assertions: + - violations: no + - name: example-allowed-ss + object: samples/storageclass/example_allowed_ss.yaml + inventory: + - samples/storageclass/example_inventory_allowed_storageclass.yaml + assertions: + - violations: no + - name: example-disallowed-pvc-badname + object: samples/storageclass/example_disallowed_pvc_badname.yaml + assertions: + - violations: yes + - name: example-disallowed-ssvct-badnamename + object: samples/storageclass/example_disallowed_ssvct_badnamename.yaml + assertions: + - violations: yes + - name: example-disallowed-pvc-nonamename + object: samples/storageclass/example_disallowed_pvc_nonamename.yaml + assertions: + - violations: yes + - name: example-disallowed-ssvct-nonamename + object: samples/storageclass/example_disallowed_ssvct_nonamename.yaml + assertions: + - violations: yes +- name: storageclass-allowlist + template: template.yaml + constraint: samples/storageclass-allowlist/constraint.yaml + cases: + - name: allowed-storage-class-pvc + object: samples/storageclass-allowlist/example_allowed.yaml + inventory: + - samples/storageclass-allowlist/example_inventory_allowed_storageclass.yaml + assertions: + - violations: no + - name: disallowed-storage-class-pvc + object: samples/storageclass-allowlist/example_disallowed.yaml + inventory: + - samples/storageclass-allowlist/example_inventory_allowed_storageclass.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/storageclass/1.1.1/sync.yaml b/artifacthub/library/general/storageclass/1.1.1/sync.yaml new file mode 100644 index 000000000..9d7fd5e16 --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/sync.yaml @@ -0,0 +1,11 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "storage.k8s.io" + version: "v1" + kind: "StorageClass" diff --git a/artifacthub/library/general/storageclass/1.1.1/template.yaml b/artifacthub/library/general/storageclass/1.1.1/template.yaml new file mode 100644 index 000000000..b1bf0748c --- /dev/null +++ b/artifacthub/library/general/storageclass/1.1.1/template.yaml @@ -0,0 +1,155 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8sstorageclass + annotations: + metadata.gatekeeper.sh/title: "Storage Class" + metadata.gatekeeper.sh/version: 1.1.1 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups":["storage.k8s.io"], + "versions": ["v1"], + "kinds": ["StorageClass"] + } + ] + ]" + description: >- + Requires storage classes to be specified when used. Only Gatekeeper 3.9+ is supported. +spec: + crd: + spec: + names: + kind: K8sStorageClass + validation: + openAPIV3Schema: + type: object + description: >- + Requires storage classes to be specified when used. + properties: + includeStorageClassesInMessage: + type: boolean + default: true + allowedStorageClasses: + type: array + description: "An optional allow-list of storage classes. If specified, any storage class not in the `allowedStorageClasses` parameter is disallowed." + items: + type: string + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8sstorageclass + + is_pvc(obj) { + obj.apiVersion == "v1" + obj.kind == "PersistentVolumeClaim" + } + + is_statefulset(obj) { + obj.apiVersion == "apps/v1" + obj.kind == "StatefulSet" + } + + violation[{"msg": msg}] { + not data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"] + msg := sprintf("StorageClasses not synced. Gatekeeper may be misconfigured. Please have a cluster-admin consult the documentation.", []) + } + + storageclass_allowed(name) { + data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][name] + # support both direct use of * and as the default value + object.get(input.parameters, "allowedStorageClasses", ["*"])[_] == "*" + } + + storageclass_allowed(name) { + data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][name] + input.parameters.allowedStorageClasses[_] == name + } + + violation[{"msg": pvc_storageclass_badname_msg}] { + is_pvc(input.review.object) + not storageclass_allowed(input.review.object.spec.storageClassName) + } + pvc_storageclass_badname_msg := sprintf("pvc did not specify a valid storage class name <%v>. Must be one of [%v]", args) { + input.parameters.includeStorageClassesInMessage + object.get(input.parameters, "allowedStorageClasses", null) == null + args := [ + input.review.object.spec.storageClassName, + concat(", ", [n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]]) + ] + } else := sprintf("pvc did not specify an allowed and valid storage class name <%v>. Must be one of [%v]", args) { + input.parameters.includeStorageClassesInMessage + object.get(input.parameters, "allowedStorageClasses", null) != null + sc := {n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]} & {x | x = object.get(input.parameters, "allowedStorageClasses", [])[_]} + args := [ + input.review.object.spec.storageClassName, + concat(", ", sc) + ] + } else := sprintf( + "pvc did not specify a valid storage class name <%v>.", + [input.review.object.spec.storageClassName] + ) + + violation[{"msg": pvc_storageclass_noname_msg}] { + is_pvc(input.review.object) + not input.review.object.spec.storageClassName + } + pvc_storageclass_noname_msg := sprintf("pvc did not specify a storage class name. Must be one of [%v]", args) { + input.parameters.includeStorageClassesInMessage + args := [ + concat(", ", [n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]]) + ] + } else := sprintf( + "pvc did not specify a storage class name.", + [] + ) + + violation[{"msg": statefulset_vct_badname_msg(vct)}] { + is_statefulset(input.review.object) + vct := input.review.object.spec.volumeClaimTemplates[_] + not storageclass_allowed(vct.spec.storageClassName) + } + statefulset_vct_badname_msg(vct) := msg { + input.parameters.includeStorageClassesInMessage + object.get(input.parameters, "allowedStorageClasses", null) == null + msg := sprintf( + "statefulset did not specify a valid storage class name <%v>. Must be one of [%v]", [ + vct.spec.storageClassName, + concat(", ", [n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]]) + ]) + } + statefulset_vct_badname_msg(vct) := msg { + input.parameters.includeStorageClassesInMessage + object.get(input.parameters, "allowedStorageClasses", null) != null + sc := {n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]} & {x | x = object.get(input.parameters, "allowedStorageClasses", [])[_]} + msg := sprintf( + "statefulset did not specify an allowed and valid storage class name <%v>. Must be one of [%v]", [ + vct.spec.storageClassName, + concat(", ", sc) + ]) + } + statefulset_vct_badname_msg(vct) := msg { + not input.parameters.includeStorageClassesInMessage + msg := sprintf( + "statefulset did not specify a valid storage class name <%v>.", [ + vct.spec.storageClassName + ]) + } + + violation[{"msg": statefulset_vct_noname_msg}] { + is_statefulset(input.review.object) + vct := input.review.object.spec.volumeClaimTemplates[_] + not vct.spec.storageClassName + } + statefulset_vct_noname_msg := sprintf("statefulset did not specify a storage class name. Must be one of [%v]", args) { + input.parameters.includeStorageClassesInMessage + args := [ + concat(", ", [n | data.inventory.cluster["storage.k8s.io/v1"]["StorageClass"][n]]) + ] + } else := sprintf( + "statefulset did not specify a storage class name.", + [] + ) + + #FIXME pod generic ephemeral might be good to validate some day too. diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/artifacthub-pkg.yml b/artifacthub/library/general/uniqueingresshost/1.0.3/artifacthub-pkg.yml new file mode 100644 index 000000000..3b20ce27f --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.3 +name: k8suniqueingresshost +displayName: Unique Ingress Host +createdAt: "2023-06-12T20:51:47Z" +description: |- + Requires all Ingress rule hosts to be unique. + Does not handle hostname wildcards: https://kubernetes.io/docs/concepts/services-networking/ingress/ +digest: 00196c02161e0cdcfa9d71ea5e2cd620f97d37a12250cc1bccb0c1187b9056c2 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/uniqueingresshost +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Unique Ingress Host + Requires all Ingress rule hosts to be unique. + Does not handle hostname wildcards: https://kubernetes.io/docs/concepts/services-networking/ingress/ +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/uniqueingresshost/1.0.3/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/kustomization.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/constraint.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/constraint.yaml new file mode 100644 index 000000000..b4d7f852f --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/constraint.yaml @@ -0,0 +1,9 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sUniqueIngressHost +metadata: + name: unique-ingress-host +spec: + match: + kinds: + - apiGroups: ["extensions", "networking.k8s.io"] + kinds: ["Ingress"] diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_allowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_allowed.yaml new file mode 100644 index 000000000..1e819e200 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_allowed.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-allowed + namespace: default +spec: + rules: + - host: example-allowed-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 + - host: example-allowed-host1.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx2 + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed.yaml new file mode 100644 index 000000000..c61893ed6 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-disallowed + namespace: default +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed2.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed2.yaml new file mode 100644 index 000000000..1ca131f13 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_disallowed2.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-disallowed2 + namespace: default +spec: + rules: + - host: example-host2.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 + - host: example-host3.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx2 + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed.yaml new file mode 100644 index 000000000..06bc70922 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-example + namespace: default +spec: + rules: + - host: example-host.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed2.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed2.yaml new file mode 100644 index 000000000..3f826aeeb --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/samples/unique-ingress-host/example_inventory_disallowed2.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-host-example2 + namespace: default +spec: + rules: + - host: example-host2.example.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: nginx + port: + number: 80 diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/suite.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/suite.yaml new file mode 100644 index 000000000..630838d1d --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/suite.yaml @@ -0,0 +1,25 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: uniqueingresshost +tests: +- name: unique-ingress-host + template: template.yaml + constraint: samples/unique-ingress-host/constraint.yaml + cases: + - name: example-allowed + object: samples/unique-ingress-host/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/unique-ingress-host/example_disallowed.yaml + inventory: + - samples/unique-ingress-host/example_inventory_disallowed.yaml + assertions: + - violations: yes + - name: example-disallowed2 + object: samples/unique-ingress-host/example_disallowed2.yaml + inventory: + - samples/unique-ingress-host/example_inventory_disallowed2.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/sync.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/sync.yaml new file mode 100644 index 000000000..ce25235ac --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/sync.yaml @@ -0,0 +1,17 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "extensions" + version: "v1beta1" + kind: "Ingress" + - group: "networking.k8s.io" + version: "v1beta1" + kind: "Ingress" + - group: "networking.k8s.io" + version: "v1" + kind: "Ingress" diff --git a/artifacthub/library/general/uniqueingresshost/1.0.3/template.yaml b/artifacthub/library/general/uniqueingresshost/1.0.3/template.yaml new file mode 100644 index 000000000..2f6c2efa6 --- /dev/null +++ b/artifacthub/library/general/uniqueingresshost/1.0.3/template.yaml @@ -0,0 +1,52 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8suniqueingresshost + annotations: + metadata.gatekeeper.sh/title: "Unique Ingress Host" + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups": ["extensions"], + "versions": ["v1beta1"], + "kinds": ["Ingress"] + }, + { + "groups": ["networking.k8s.io"], + "versions": ["v1beta1", "v1"], + "kinds": ["Ingress"] + } + ] + ]" + description: >- + Requires all Ingress rule hosts to be unique. + + Does not handle hostname wildcards: + https://kubernetes.io/docs/concepts/services-networking/ingress/ +spec: + crd: + spec: + names: + kind: K8sUniqueIngressHost + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8suniqueingresshost + + identical(obj, review) { + obj.metadata.namespace == review.object.metadata.namespace + obj.metadata.name == review.object.metadata.name + } + + violation[{"msg": msg}] { + input.review.kind.kind == "Ingress" + re_match("^(extensions|networking.k8s.io)$", input.review.kind.group) + host := input.review.object.spec.rules[_].host + other := data.inventory.namespace[_][otherapiversion]["Ingress"][name] + re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion) + other.spec.rules[_].host == host + not identical(other, input.review) + msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host]) + } diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/artifacthub-pkg.yml b/artifacthub/library/general/uniqueserviceselector/1.0.2/artifacthub-pkg.yml new file mode 100644 index 000000000..548030cba --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/artifacthub-pkg.yml @@ -0,0 +1,25 @@ +version: 1.0.2 +name: k8suniqueserviceselector +displayName: Unique Service Selector +createdAt: "2023-06-12T20:47:48Z" +description: |- + Requires Services to have unique selectors within a namespace. Selectors are considered the same if they have identical keys and values. Selectors may share a key/value pair so long as there is at least one distinct key/value pair between them. + https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service +digest: ccb39d306eae45a9be7a0b1df4f686e2a38e1c73a1f2d4ab37f2f01ef626bdf4 +license: Apache-2.0 +homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/uniqueserviceselector +keywords: + - gatekeeper + - open-policy-agent + - policies +readme: |- + # Unique Service Selector + Requires Services to have unique selectors within a namespace. Selectors are considered the same if they have identical keys and values. Selectors may share a key/value pair so long as there is at least one distinct key/value pair between them. + https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service +install: |- + ### Usage + ```shell + kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/uniqueserviceselector/1.0.2/template.yaml + ``` +provider: + name: Gatekeeper Library diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/kustomization.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/kustomization.yaml new file mode 100644 index 000000000..7d70d11b7 --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - template.yaml diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/constraint.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/constraint.yaml new file mode 100644 index 000000000..3a00cd8b1 --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/constraint.yaml @@ -0,0 +1,6 @@ +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: K8sUniqueServiceSelector +metadata: + name: unique-service-selector + labels: + owner: admin.agilebank.demo diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_allowed.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_allowed.yaml new file mode 100644 index 000000000..1d69847d9 --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_allowed.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: gatekeeper-test-service-disallowed + namespace: default +spec: + ports: + - port: 443 + selector: + key: other-value diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_disallowed.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_disallowed.yaml new file mode 100644 index 000000000..6062ce7ff --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_disallowed.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: gatekeeper-test-service-disallowed + namespace: default +spec: + ports: + - port: 443 + selector: + key: value diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_inventory_disallowed.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_inventory_disallowed.yaml new file mode 100644 index 000000000..19c1aa7ea --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/samples/unique-service-selector/example_inventory_disallowed.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: gatekeeper-test-service-example + namespace: default +spec: + ports: + - port: 443 + selector: + key: value diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/suite.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/suite.yaml new file mode 100644 index 000000000..abefd5d0e --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/suite.yaml @@ -0,0 +1,19 @@ +kind: Suite +apiVersion: test.gatekeeper.sh/v1alpha1 +metadata: + name: uniqueserviceselector +tests: +- name: unique-service-selector + template: template.yaml + constraint: samples/unique-service-selector/constraint.yaml + cases: + - name: example-allowed + object: samples/unique-service-selector/example_allowed.yaml + assertions: + - violations: no + - name: example-disallowed + object: samples/unique-service-selector/example_disallowed.yaml + inventory: + - samples/unique-service-selector/example_inventory_disallowed.yaml + assertions: + - violations: yes diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/sync.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/sync.yaml new file mode 100644 index 000000000..433294b0f --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/sync.yaml @@ -0,0 +1,11 @@ +apiVersion: config.gatekeeper.sh/v1alpha1 +kind: Config +metadata: + name: config + namespace: "gatekeeper-system" +spec: + sync: + syncOnly: + - group: "" + version: "v1" + kind: "Service" diff --git a/artifacthub/library/general/uniqueserviceselector/1.0.2/template.yaml b/artifacthub/library/general/uniqueserviceselector/1.0.2/template.yaml new file mode 100644 index 000000000..8fb9eb2f4 --- /dev/null +++ b/artifacthub/library/general/uniqueserviceselector/1.0.2/template.yaml @@ -0,0 +1,69 @@ +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: + name: k8suniqueserviceselector + annotations: + metadata.gatekeeper.sh/title: "Unique Service Selector" + metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/requires-sync-data: | + "[ + [ + { + "groups":[""], + "versions": ["v1"], + "kinds": ["Service"] + } + ] + ]" + description: >- + Requires Services to have unique selectors within a namespace. + Selectors are considered the same if they have identical keys and values. + Selectors may share a key/value pair so long as there is at least one + distinct key/value pair between them. + + https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service +spec: + crd: + spec: + names: + kind: K8sUniqueServiceSelector + targets: + - target: admission.k8s.gatekeeper.sh + rego: | + package k8suniqueserviceselector + + make_apiversion(kind) = apiVersion { + g := kind.group + v := kind.version + g != "" + apiVersion = sprintf("%v/%v", [g, v]) + } + + make_apiversion(kind) = apiVersion { + kind.group == "" + apiVersion = kind.version + } + + identical(obj, review) { + obj.metadata.namespace == review.namespace + obj.metadata.name == review.name + obj.kind == review.kind.kind + obj.apiVersion == make_apiversion(review.kind) + } + + flatten_selector(obj) = flattened { + selectors := [s | s = concat(":", [key, val]); val = obj.spec.selector[key]] + flattened := concat(",", sort(selectors)) + } + + violation[{"msg": msg}] { + input.review.kind.kind == "Service" + input.review.kind.version == "v1" + input.review.kind.group == "" + input_selector := flatten_selector(input.review.object) + other := data.inventory.namespace[namespace][_]["Service"][name] + not identical(other, input.review) + other_selector := flatten_selector(other) + input_selector == other_selector + msg := sprintf("same selector as service <%v> in namespace <%v>", [name, namespace]) + } diff --git a/library/general/horizontalpodautoscaler/template.yaml b/library/general/horizontalpodautoscaler/template.yaml index 1e15438db..3e43f28a7 100644 --- a/library/general/horizontalpodautoscaler/template.yaml +++ b/library/general/horizontalpodautoscaler/template.yaml @@ -4,8 +4,8 @@ metadata: name: k8shorizontalpodautoscaler annotations: metadata.gatekeeper.sh/title: "Horizontal Pod Autoscaler" - metadata.gatekeeper.sh/version: 1.0.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/library/general/poddisruptionbudget/template.yaml b/library/general/poddisruptionbudget/template.yaml index a0e9b8fba..d44000824 100644 --- a/library/general/poddisruptionbudget/template.yaml +++ b/library/general/poddisruptionbudget/template.yaml @@ -4,8 +4,8 @@ metadata: name: k8spoddisruptionbudget annotations: metadata.gatekeeper.sh/title: "Pod Disruption Budget" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/library/general/storageclass/template.yaml b/library/general/storageclass/template.yaml index 26d281615..b1bf0748c 100644 --- a/library/general/storageclass/template.yaml +++ b/library/general/storageclass/template.yaml @@ -4,8 +4,8 @@ metadata: name: k8sstorageclass annotations: metadata.gatekeeper.sh/title: "Storage Class" - metadata.gatekeeper.sh/version: 1.1.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.1.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/library/general/uniqueingresshost/template.yaml b/library/general/uniqueingresshost/template.yaml index cc1e11a03..2f6c2efa6 100644 --- a/library/general/uniqueingresshost/template.yaml +++ b/library/general/uniqueingresshost/template.yaml @@ -4,8 +4,8 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/library/general/uniqueserviceselector/template.yaml b/library/general/uniqueserviceselector/template.yaml index f9252daa5..8fb9eb2f4 100644 --- a/library/general/uniqueserviceselector/template.yaml +++ b/library/general/uniqueserviceselector/template.yaml @@ -4,8 +4,8 @@ metadata: name: k8suniqueserviceselector annotations: metadata.gatekeeper.sh/title: "Unique Service Selector" - metadata.gatekeeper.sh/version: 1.0.1 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/scripts/require-sync/main.go b/scripts/require-sync/main.go index f27d6706f..1d5f9632e 100644 --- a/scripts/require-sync/main.go +++ b/scripts/require-sync/main.go @@ -23,7 +23,7 @@ import ( "k8s.io/utils/strings/slices" ) -const syncAnnotation string = "metadata.gatekeeper.sh/requiresSyncData" +const syncAnnotation string = "metadata.gatekeeper.sh/requires-sync-data" var ( pathFlag = flag.String("path", "", "Path to verify referential templates include sync data.") diff --git a/src/general/horizontalpodautoscaler/constraint.tmpl b/src/general/horizontalpodautoscaler/constraint.tmpl index db32145fb..b00b6a6d3 100644 --- a/src/general/horizontalpodautoscaler/constraint.tmpl +++ b/src/general/horizontalpodautoscaler/constraint.tmpl @@ -4,8 +4,8 @@ metadata: name: k8shorizontalpodautoscaler annotations: metadata.gatekeeper.sh/title: "Horizontal Pod Autoscaler" - metadata.gatekeeper.sh/version: 1.0.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/src/general/poddisruptionbudget/constraint.tmpl b/src/general/poddisruptionbudget/constraint.tmpl index 12ef960b5..d46a8d493 100644 --- a/src/general/poddisruptionbudget/constraint.tmpl +++ b/src/general/poddisruptionbudget/constraint.tmpl @@ -4,8 +4,8 @@ metadata: name: k8spoddisruptionbudget annotations: metadata.gatekeeper.sh/title: "Pod Disruption Budget" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/src/general/storageclass/constraint.tmpl b/src/general/storageclass/constraint.tmpl index 482b535ce..8b46ac7e5 100644 --- a/src/general/storageclass/constraint.tmpl +++ b/src/general/storageclass/constraint.tmpl @@ -4,8 +4,8 @@ metadata: name: k8sstorageclass annotations: metadata.gatekeeper.sh/title: "Storage Class" - metadata.gatekeeper.sh/version: 1.1.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.1.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/src/general/uniqueingresshost/constraint.tmpl b/src/general/uniqueingresshost/constraint.tmpl index 513a2abe5..e546c9098 100644 --- a/src/general/uniqueingresshost/constraint.tmpl +++ b/src/general/uniqueingresshost/constraint.tmpl @@ -4,8 +4,8 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/src/general/uniqueserviceselector/constraint.tmpl b/src/general/uniqueserviceselector/constraint.tmpl index d2a0c782c..e4bb1470f 100644 --- a/src/general/uniqueserviceselector/constraint.tmpl +++ b/src/general/uniqueserviceselector/constraint.tmpl @@ -4,8 +4,8 @@ metadata: name: k8suniqueserviceselector annotations: metadata.gatekeeper.sh/title: "Unique Service Selector" - metadata.gatekeeper.sh/version: 1.0.1 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/website/docs/validation/horizontalpodautoscaler.md b/website/docs/validation/horizontalpodautoscaler.md index 3431a1c7e..5a638c41c 100644 --- a/website/docs/validation/horizontalpodautoscaler.md +++ b/website/docs/validation/horizontalpodautoscaler.md @@ -16,8 +16,8 @@ metadata: name: k8shorizontalpodautoscaler annotations: metadata.gatekeeper.sh/title: "Horizontal Pod Autoscaler" - metadata.gatekeeper.sh/version: 1.0.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/website/docs/validation/poddisruptionbudget.md b/website/docs/validation/poddisruptionbudget.md index 3733cfddb..c5c56d192 100644 --- a/website/docs/validation/poddisruptionbudget.md +++ b/website/docs/validation/poddisruptionbudget.md @@ -17,8 +17,8 @@ metadata: name: k8spoddisruptionbudget annotations: metadata.gatekeeper.sh/title: "Pod Disruption Budget" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/website/docs/validation/storageclass.md b/website/docs/validation/storageclass.md index bd0a4521f..048cbe87c 100644 --- a/website/docs/validation/storageclass.md +++ b/website/docs/validation/storageclass.md @@ -16,8 +16,8 @@ metadata: name: k8sstorageclass annotations: metadata.gatekeeper.sh/title: "Storage Class" - metadata.gatekeeper.sh/version: 1.1.0 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.1.1 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/website/docs/validation/uniqueingresshost.md b/website/docs/validation/uniqueingresshost.md index eaed5db69..d8b14494c 100644 --- a/website/docs/validation/uniqueingresshost.md +++ b/website/docs/validation/uniqueingresshost.md @@ -17,8 +17,8 @@ metadata: name: k8suniqueingresshost annotations: metadata.gatekeeper.sh/title: "Unique Ingress Host" - metadata.gatekeeper.sh/version: 1.0.2 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.3 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ { diff --git a/website/docs/validation/uniqueserviceselector.md b/website/docs/validation/uniqueserviceselector.md index f055ba7a4..dd55a4737 100644 --- a/website/docs/validation/uniqueserviceselector.md +++ b/website/docs/validation/uniqueserviceselector.md @@ -17,8 +17,8 @@ metadata: name: k8suniqueserviceselector annotations: metadata.gatekeeper.sh/title: "Unique Service Selector" - metadata.gatekeeper.sh/version: 1.0.1 - metadata.gatekeeper.sh/requiresSyncData: | + metadata.gatekeeper.sh/version: 1.0.2 + metadata.gatekeeper.sh/requires-sync-data: | "[ [ {