mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 17:16:59 +02:00
fix(helm): resolve RBAC permissions for namespaced gateway sources (#5578)
* fix(helm): resolve RBAC permissions for namespaced gateway sources * feat(helm): add support for gateway namespace in RBAC configuration * chore(helm): update docs and fix formatting issues * fix(helm): revert README changes and add gatewayNamespace docs * chore lint fmt
This commit is contained in:
parent
a386197f0a
commit
a270a32bf6
@ -109,6 +109,7 @@ If `namespaced` is set to `true`, please ensure that `sources` my only contains
|
||||
| extraVolumeMounts | list | `[]` | Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container. |
|
||||
| extraVolumes | list | `[]` | Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`. |
|
||||
| fullnameOverride | string | `nil` | Override the full name of the chart. |
|
||||
| gatewayNamespace | string | `nil` | _Gateway API_ gateway namespace to watch. |
|
||||
| global.imagePullSecrets | list | `[]` | Global image pull secrets. |
|
||||
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy for the `external-dns` container. |
|
||||
| image.repository | string | `"registry.k8s.io/external-dns/external-dns"` | Image repository for the `external-dns` container. |
|
||||
|
@ -103,3 +103,12 @@ labelSelector:
|
||||
matchLabels:
|
||||
{{ include "external-dns.selectorLabels" . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Check if any Gateway API sources are enabled
|
||||
*/}}
|
||||
{{- define "external-dns.hasGatewaySources" -}}
|
||||
{{- if or (has "gateway-httproute" .Values.sources) (has "gateway-grpcroute" .Values.sources) (has "gateway-tlsroute" .Values.sources) (has "gateway-tcproute" .Values.sources) (has "gateway-udproute" .Values.sources) -}}
|
||||
true
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
@ -58,14 +58,18 @@ rules:
|
||||
resources: ["dnsendpoints/status"]
|
||||
verbs: ["*"]
|
||||
{{- end }}
|
||||
{{- if or (has "gateway-httproute" .Values.sources) (has "gateway-grpcroute" .Values.sources) (has "gateway-tlsroute" .Values.sources) (has "gateway-tcproute" .Values.sources) (has "gateway-udproute" .Values.sources) }}
|
||||
{{- if include "external-dns.hasGatewaySources" . }}
|
||||
{{- if or (not .Values.namespaced) (and .Values.namespaced (not .Values.gatewayNamespace)) }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if not .Values.namespaced }}
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if has "gateway-httproute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["httproutes"]
|
||||
@ -127,4 +131,31 @@ rules:
|
||||
{{- with .Values.rbac.additionalPermissions }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- if and .Values.rbac.create .Values.namespaced (include "external-dns.hasGatewaySources" .) }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ template "external-dns.fullname" . }}-namespaces
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- if .Values.gatewayNamespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ template "external-dns.fullname" . }}-gateway
|
||||
namespace: {{ .Values.gatewayNamespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
@ -13,4 +13,39 @@ subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "external-dns.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- if and .Values.rbac.create .Values.namespaced (include "external-dns.hasGatewaySources" .) }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ template "external-dns.fullname" . }}-namespaces
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ template "external-dns.fullname" . }}-namespaces
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "external-dns.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- if .Values.gatewayNamespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ template "external-dns.fullname" . }}-gateway
|
||||
namespace: {{ .Values.gatewayNamespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "external-dns.fullname" . }}-gateway
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "external-dns.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
@ -111,6 +111,9 @@ spec:
|
||||
{{- if .Values.namespaced }}
|
||||
- --namespace={{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- if .Values.gatewayNamespace }}
|
||||
- --gateway-namespace={{ .Values.gatewayNamespace }}
|
||||
{{- end }}
|
||||
{{- range .Values.domainFilters }}
|
||||
- --domain-filter={{ . }}
|
||||
{{- end }}
|
||||
|
@ -156,3 +156,238 @@ tests:
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["udproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create Role instead of ClusterRole when namespaced is true
|
||||
set:
|
||||
namespaced: true
|
||||
sources:
|
||||
- service
|
||||
asserts:
|
||||
- isKind:
|
||||
of: Role
|
||||
template: clusterrole.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
|
||||
- it: should create RoleBinding instead of ClusterRoleBinding when namespaced is true
|
||||
set:
|
||||
namespaced: true
|
||||
sources:
|
||||
- service
|
||||
asserts:
|
||||
- isKind:
|
||||
of: RoleBinding
|
||||
template: clusterrolebinding.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-viewer
|
||||
template: clusterrolebinding.yaml
|
||||
|
||||
- it: should create all required resources when namespaced=true and gatewayNamespace is specified
|
||||
set:
|
||||
namespaced: true
|
||||
gatewayNamespace: gateway-ns
|
||||
sources:
|
||||
- gateway-httproute
|
||||
asserts:
|
||||
# Should have: main Role + ClusterRole for namespaces + Gateway Role
|
||||
- hasDocuments:
|
||||
count: 3
|
||||
template: clusterrole.yaml
|
||||
- hasDocuments:
|
||||
count: 3
|
||||
template: clusterrolebinding.yaml
|
||||
|
||||
# Main role should exist and contain route permissions but NOT gateway permissions
|
||||
- isKind:
|
||||
of: Role
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["httproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
- notContains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
|
||||
# ClusterRole for namespaces should exist
|
||||
- isKind:
|
||||
of: ClusterRole
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-namespaces
|
||||
template: clusterrole.yaml
|
||||
|
||||
# Gateway role should exist and have gateway permissions only
|
||||
- isKind:
|
||||
of: Role
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-gateway
|
||||
template: clusterrole.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: gateway-ns
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-gateway
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-gateway
|
||||
template: clusterrole.yaml
|
||||
|
||||
|
||||
- it: should create main Role with gateway permissions and ClusterRole for namespaces when namespaced=true and gatewayNamespace is not set
|
||||
set:
|
||||
namespaced: true
|
||||
sources:
|
||||
- gateway-httproute
|
||||
asserts:
|
||||
# Should have: main Role + ClusterRole for namespaces
|
||||
- hasDocuments:
|
||||
count: 2
|
||||
template: clusterrole.yaml
|
||||
- hasDocuments:
|
||||
count: 2
|
||||
template: clusterrolebinding.yaml
|
||||
# Main Role should exist and contain gateway permissions
|
||||
- isKind:
|
||||
of: Role
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["httproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
# ClusterRole for namespaces should exist
|
||||
- isKind:
|
||||
of: ClusterRole
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-namespaces
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
documentSelector:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-namespaces
|
||||
template: clusterrole.yaml
|
||||
|
||||
- it: should create ClusterRole with all permissions when namespaced=false and gateway sources exist
|
||||
set:
|
||||
namespaced: false
|
||||
sources:
|
||||
- gateway-httproute
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrole.yaml
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrolebinding.yaml
|
||||
- isKind:
|
||||
of: ClusterRole
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
template: clusterrole.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
template: clusterrole.yaml
|
||||
|
||||
- it: should create only ClusterRole when namespaced=false and no gateway sources
|
||||
set:
|
||||
namespaced: false
|
||||
sources:
|
||||
- service
|
||||
- ingress
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrole.yaml
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrolebinding.yaml
|
||||
- isKind:
|
||||
of: ClusterRole
|
||||
template: clusterrole.yaml
|
||||
- notContains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups: ["gateway.networking.k8s.io"]
|
||||
template: clusterrole.yaml
|
||||
|
||||
- it: should create only Role when namespaced=true and no gateway sources
|
||||
set:
|
||||
namespaced: true
|
||||
sources:
|
||||
- service
|
||||
- ingress
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrole.yaml
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
template: clusterrolebinding.yaml
|
||||
- isKind:
|
||||
of: Role
|
||||
template: clusterrole.yaml
|
||||
- isKind:
|
||||
of: RoleBinding
|
||||
template: clusterrolebinding.yaml
|
||||
|
@ -205,6 +205,9 @@ triggerLoopOnEvent: false
|
||||
# -- if `true`, _ExternalDNS_ will run in a namespaced scope (`Role`` and `Rolebinding`` will be namespaced too).
|
||||
namespaced: false
|
||||
|
||||
# -- _Gateway API_ gateway namespace to watch.
|
||||
gatewayNamespace: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- _Kubernetes_ resources to monitor for DNS entries.
|
||||
sources:
|
||||
- service
|
||||
|
Loading…
Reference in New Issue
Block a user