From 8cb970f3bfcbd80206c15f03a0e56803929c6821 Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Wed, 23 Oct 2024 14:13:30 +0200 Subject: [PATCH] admission-control: validate that Ingress and RouteGroup hosts in hosted zone domain Add ValidatingAdmissionPolicy that validates Ingress and RouteGroup hosts from hosted zone parent domain are in hosted zone domain. E.g. for hosted zone `foo.bar.test` its parent domain is `bar.test` and therefore Ingress and RouteGroup hosts from `bar.test` domain must also be in `foo.bar.test` domain. Signed-off-by: Alexander Yastrebov --- .../01-admission-control/hostname-policy.yaml | 56 +++++++++++++++++++ cluster/manifests/deletions.yaml | 7 +++ 2 files changed, 63 insertions(+) create mode 100644 cluster/manifests/01-admission-control/hostname-policy.yaml diff --git a/cluster/manifests/01-admission-control/hostname-policy.yaml b/cluster/manifests/01-admission-control/hostname-policy.yaml new file mode 100644 index 0000000000..36d069a361 --- /dev/null +++ b/cluster/manifests/01-admission-control/hostname-policy.yaml @@ -0,0 +1,56 @@ +# {{ if or (eq .Cluster.ConfigItems.ingresses_validation "enabled") (eq .Cluster.ConfigItems.routegroups_validation "enabled") }} +# {{ $hosted_zone_parent_domain := slice (split .Values.hosted_zone ".") 1 | join "." }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: hostname-policy.teapot.zalan.do + annotations: + kubernetes.io/description: | + Validates that Ingress and RouteGroup hosts are in {{ .Values.hosted_zone }} domain. +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + # {{ if eq .Cluster.ConfigItems.ingresses_validation "enabled" }} + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + # {{ end }} + # {{ if eq .Cluster.ConfigItems.routegroups_validation "enabled" }} + - apiGroups: ["zalando.org"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["routegroups"] + # {{ end }} + matchConditions: + # exclude owned resources, e.g. created by StackSet and FabricGateway controllers. + - name: exclude-owned-resources + expression: | + !has(object.metadata.ownerReferences) + validations: + # {{ if eq .Cluster.ConfigItems.ingresses_validation "enabled" }} + - message: Ingress host must be in {{ .Values.hosted_zone }} domain + expression: | + object.kind == "Ingress" && + object.spec.rules + .exists(r, r.host.endsWith(".{{ $hosted_zone_parent_domain }}") && !r.host.endsWith(".{{ .Values.hosted_zone }}")) + reason: Invalid + # {{ end }} + # {{ if eq .Cluster.ConfigItems.routegroups_validation "enabled" }} + - message: RouteGroup host must be in {{ .Values.hosted_zone }} domain + expression: | + object.kind == "RouteGroup" && + object.spec.hosts + .exists(h, h.endsWith(".{{ $hosted_zone_parent_domain }}") && !h.endsWith(".{{ .Values.hosted_zone }}")) + reason: Invalid + # {{ end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: hostname-policy-binding.teapot.zalan.do +spec: + policyName: hostname-policy.teapot.zalan.do + validationActions: [Deny] +# {{ end }} diff --git a/cluster/manifests/deletions.yaml b/cluster/manifests/deletions.yaml index 401057c9a8..fbe2cb5507 100644 --- a/cluster/manifests/deletions.yaml +++ b/cluster/manifests/deletions.yaml @@ -320,3 +320,10 @@ post_apply: kind: Service namespace: kube-system {{- end }} + +# {{ if and (ne .Cluster.ConfigItems.ingresses_validation "enabled") (ne .Cluster.ConfigItems.routegroups_validation "enabled") }} +- kind: ValidatingAdmissionPolicyBinding + name: hostname-policy-binding.teapot.zalan.do +- kind: ValidatingAdmissionPolicy + name: hostname-policy.teapot.zalan.do +# {{ end }}