pkg/safeguards/lib/v1.0.0/unique-service-selectors/template.yaml (64 lines of code) (raw):

apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8sazurev1uniqueserviceselector annotations: metadata.gatekeeper.sh/title: "Unique Service Selectors" metadata.gatekeeper.sh/version: 1.0.0 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: K8sAzureV1UniqueServiceSelector targets: - target: admission.k8s.gatekeeper.sh rego: | package k8sazurev1uniqueserviceselector make_apiversion(kind) = apiVersion { g := kind.group v := kind.version g != "" apiVersion = sprintf("%s/%s", [g, v]) } make_apiversion(kind) = apiVersion { kind.group == "" apiVersion = kind.version } identical(obj, review) { obj.metadata.namespace == review.object.metadata.namespace obj.metadata.name == review.object.metadata.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_namespace := input.review.object.metadata.namespace input_selector := flatten_selector(input.review.object) other := data.inventory.namespace[input_namespace]["v1"].Service[_] not identical(other, input.review) other_selector := flatten_selector(other) input_selector == other_selector msg := sprintf("same selector as service <%s> in namespace <%s>", [other.metadata.name, input_namespace]) }