Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gatekeeper-config/charts/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
apiVersion: v2
description: Helm chart deploying OPA Gatekeeper ConstraintTemplates and Constraints for Kubernetes admission control.
name: gatekeeper-config
version: 0.2.0
appVersion: 0.2.0
version: 0.3.0
appVersion: 0.3.0
icon: https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/logo/gatekeeper-horizontal-color.png
keywords:
- gatekeeper
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{- if .Values.policies.ingressAnnotations.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GkIngressAnnotations
metadata:
name: ingress-annotations-insecure-snippets
labels:
severity: 'info'
spec:
enforcementAction: {{ .Values.policies.ingressAnnotations.enforcementAction }}
match:
kinds:
- apiGroups: ["networking.k8s.io"]
kinds: ["Ingress"]
scope: Namespaced
parameters:
hint: 'disabled due to CVE-2021-25742'
regexes:
- '^(?:nginx\.)?ingress\.kubernetes\.io/(?:auth|configuration|server|modsecurity)-snippet$'
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if .Values.policies.ingressAnnotationsMigration.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GkIngressAnnotationsMigration
metadata:
name: ingress-annotations-migration
labels:
severity: 'error'
spec:
enforcementAction: {{ .Values.policies.ingressAnnotationsMigration.enforcementAction }}
match:
kinds:
- apiGroups: ["networking.k8s.io"]
kinds: ["Ingress"]
scope: Namespaced
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{- if .Values.policies.ingressAnnotations.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GkIngressAnnotations
metadata:
name: ingress-annotations-wrong-prefix
labels:
severity: 'info'
spec:
enforcementAction: {{ .Values.policies.ingressAnnotations.enforcementAction }}
match:
kinds:
- apiGroups: ["networking.k8s.io"]
kinds: ["Ingress"]
scope: Namespaced
parameters:
hint: 'use the prefix "nginx.ingress.kubernetes.io/" instead (the legacy "ingress.kubernetes.io/" prefix is deprecated)'
regexes:
- '^ingress\.kubernetes\.io/'
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if .Values.policies.prometheusScrapeAnnotations.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GkPrometheusScrapeAnnotations
metadata:
name: prometheus-scrape-annotations
labels:
severity: 'debug'
spec:
enforcementAction: {{ .Values.policies.prometheusScrapeAnnotations.enforcementAction }}
match:
kinds:
- apiGroups: [""]
kinds: ["Pod", "Service"]
scope: Namespaced
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{{- if .Values.policies.ingressAnnotationsMigration.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: gkingressannotationsmigration
spec:
crd:
spec:
names:
kind: GkIngressAnnotationsMigration

targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: Rego
source:
version: "v1"
libs:
- |
{{ include "gatekeeper-config.lib.add_support_labels" . | indent 16 }}
rego: |
package ingressannotationsmigration

import data.lib.add_support_labels

iro := input.review.object
annotations := object.get(iro, ["metadata", "annotations"], {})

violation contains {"msg": add_support_labels.from_k8s_object(iro, msg)} if {
iro.kind == "Ingress"

oldValue := annotations[oldKey]
startswith(oldKey, "ingress.kubernetes.io/")
subkey := trim_prefix(oldKey, "ingress.kubernetes.io/")
newKey := sprintf("nginx.ingress.kubernetes.io/%s", [subkey])
newValue := object.get(annotations, [newKey], "<unset>")

oldValue != newValue
msg := sprintf("has not correctly migrated %s annotation (value in old annotation is %q, value in new annotation is %q)", [oldKey, oldValue, newValue])
}

violation contains {"msg": add_support_labels.from_k8s_object(iro, msg)} if {
iro.kind == "Ingress"

annotations[newKey]
startswith(newKey, "nginx.ingress.kubernetes.io/")
subkey := trim_prefix(newKey, "nginx.ingress.kubernetes.io/")
oldKey := sprintf("ingress.kubernetes.io/%s", [subkey])

object.get(annotations, [oldKey], "<unset>") == "<unset>"
msg := sprintf("has deleted %s annotation too early (still required while the legacy prefix is in use)", [oldKey])
}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{{- if .Values.policies.ingressAnnotations.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: gkingressannotations
spec:
crd:
spec:
names:
kind: GkIngressAnnotations
validation:
openAPIV3Schema:
type: object
properties:
hint:
type: string
regexes:
type: array
items:
type: string

targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: Rego
source:
version: "v1"
libs:
- |
{{ include "gatekeeper-config.lib.add_support_labels" . | indent 16 }}
rego: |
package ingressannotations

import data.lib.add_support_labels

iro := input.review.object
annotations := object.get(iro, ["metadata", "annotations"], {})

violation contains {"msg": add_support_labels.from_k8s_object(iro, msg)} if {
iro.kind == "Ingress"
annotations[key]
pattern := input.parameters.regexes[_]
regex.match(pattern, key)
msg := sprintf("has disabled annotation: %q (%s)", [key, input.parameters.hint])
}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{- if .Values.policies.prometheusScrapeAnnotations.enabled }}
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: gkprometheusscrapeannotations
spec:
crd:
spec:
names:
kind: GkPrometheusScrapeAnnotations

targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: Rego
source:
version: "v1"
libs:
- |
{{ include "gatekeeper-config.lib.add_support_labels" . | indent 16 }}
rego: |
package prometheusscrapeannotations

import data.lib.add_support_labels

iro := input.review.object

# Requires a Gatekeeper Config resource syncing
# monitoring.coreos.com/v1 Prometheus objects into the OPA cache.
# The policy defaults to disabled until that Config exists.
is_valid_target contains target if {
target := data.inventory.namespace[_]["monitoring.coreos.com/v1"].Prometheus[_].metadata.name
}

violation contains {"msg": add_support_labels.from_k8s_object(iro, msg)} if {
regex.match("^(?:Service|Pod)$", iro.kind)
anno := object.get(iro, ["metadata", "annotations"], {})
object.get(anno, "prometheus.io/scrape", "false") == "true"

targets := regex.split(`\s*,\s*`, object.get(anno, "prometheus.io/targets", ""))
count(targets) != count({t | t := targets[_]; is_valid_target[_] == t})

all_valid_targets := {t | is_valid_target[t]}

msg := sprintf(
"has prometheus.io/scrape annotation, but prometheus.io/targets annotation is missing or does not have a valid value (got: %s, valid: %s)",
[json.marshal(sort(targets)), json.marshal(sort(all_valid_targets))],
)
}
{{- end }}
12 changes: 12 additions & 0 deletions gatekeeper-config/charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,17 @@ policies:
enforcementAction: dryrun
allowlist: []

ingressAnnotations:
enabled: true
enforcementAction: dryrun

ingressAnnotationsMigration:
enabled: false
enforcementAction: dryrun

prometheusScrapeAnnotations:
enabled: false
enforcementAction: dryrun

tests:
enabled: false
46 changes: 44 additions & 2 deletions gatekeeper-config/plugindefinition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ kind: PluginDefinition
metadata:
name: gatekeeper-config
spec:
version: 0.2.0
version: 0.3.0
displayName: Gatekeeper Config
description: |
Deploys OPA Gatekeeper ConstraintTemplates and Constraints for Kubernetes
Expand All @@ -17,7 +17,7 @@ spec:
helmChart:
name: gatekeeper-config
repository: oci://ghcr.io/cloudoperators/greenhouse-extensions/charts
version: 0.2.0
version: 0.3.0
options:
- name: policies.highCpuRequests.enabled
displayName: High CPU requests policy enabled
Expand Down Expand Up @@ -148,3 +148,45 @@ spec:
is keyed by {matchNamespace, matchRepository}.
required: false
type: list

- name: policies.ingressAnnotations.enabled
displayName: Ingress annotations policy enabled
description: Enable the ingress-annotations policy (flags disabled-snippet annotations and the legacy ingress.kubernetes.io/ prefix).
default: true
required: false
type: bool
- name: policies.ingressAnnotations.enforcementAction
displayName: Ingress annotations enforcement action
description: Gatekeeper enforcementAction for ingress-annotations (dryrun, warn, or deny).
default: dryrun
required: false
type: string

- name: policies.ingressAnnotationsMigration.enabled
displayName: Ingress annotations migration policy enabled
description: Enable the ingress-annotations-migration policy (catches inconsistent or premature removal of legacy/modern annotation pairs).
default: false
required: false
type: bool
- name: policies.ingressAnnotationsMigration.enforcementAction
displayName: Ingress annotations migration enforcement action
description: Gatekeeper enforcementAction for ingress-annotations-migration (dryrun, warn, or deny).
default: dryrun
required: false
type: string

- name: policies.prometheusScrapeAnnotations.enabled
displayName: Prometheus scrape annotations policy enabled
description: |
Enable the prometheus-scrape-annotations policy (flags prometheus.io/scrape=true
annotations without a matching prometheus.io/targets entry). Requires a Gatekeeper
Config resource syncing monitoring.coreos.com/v1 Prometheus into the OPA cache.
default: false
required: false
type: bool
- name: policies.prometheusScrapeAnnotations.enforcementAction
displayName: Prometheus scrape annotations enforcement action
description: Gatekeeper enforcementAction for prometheus-scrape-annotations (dryrun, warn, or deny).
default: dryrun
required: false
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: both-matching
namespace: default
annotations:
ingress.kubernetes.io/auth-url: "https://auth.example.com"
nginx.ingress.kubernetes.io/auth-url: "https://auth.example.com"
spec:
rules: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: both-mismatched
namespace: default
annotations:
ingress.kubernetes.io/auth-url: "https://old.example.com"
nginx.ingress.kubernetes.io/auth-url: "https://new.example.com"
spec:
rules: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: new-only
namespace: default
annotations:
nginx.ingress.kubernetes.io/auth-url: "https://auth.example.com"
spec:
rules: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: old-only
namespace: default
annotations:
ingress.kubernetes.io/auth-url: "https://auth.example.com"
spec:
rules: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-snippet
namespace: default
annotations:
nginx.ingress.kubernetes.io/auth-snippet: "auth_request /auth;"
spec:
rules: []
Loading
Loading