mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 01:26: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. |
|
| 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`. |
|
| extraVolumes | list | `[]` | Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`. |
|
||||||
| fullnameOverride | string | `nil` | Override the full name of the chart. |
|
| 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. |
|
| global.imagePullSecrets | list | `[]` | Global image pull secrets. |
|
||||||
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy for the `external-dns` container. |
|
| 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. |
|
| image.repository | string | `"registry.k8s.io/external-dns/external-dns"` | Image repository for the `external-dns` container. |
|
||||||
|
@ -103,3 +103,12 @@ labelSelector:
|
|||||||
matchLabels:
|
matchLabels:
|
||||||
{{ include "external-dns.selectorLabels" . | nindent 4 }}
|
{{ include "external-dns.selectorLabels" . | nindent 4 }}
|
||||||
{{- end }}
|
{{- 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"]
|
resources: ["dnsendpoints/status"]
|
||||||
verbs: ["*"]
|
verbs: ["*"]
|
||||||
{{- end }}
|
{{- 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"]
|
- apiGroups: ["gateway.networking.k8s.io"]
|
||||||
resources: ["gateways"]
|
resources: ["gateways"]
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
|
{{- end }}
|
||||||
|
{{- if not .Values.namespaced }}
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["namespaces"]
|
resources: ["namespaces"]
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- if has "gateway-httproute" .Values.sources }}
|
{{- if has "gateway-httproute" .Values.sources }}
|
||||||
- apiGroups: ["gateway.networking.k8s.io"]
|
- apiGroups: ["gateway.networking.k8s.io"]
|
||||||
resources: ["httproutes"]
|
resources: ["httproutes"]
|
||||||
@ -127,4 +131,31 @@ rules:
|
|||||||
{{- with .Values.rbac.additionalPermissions }}
|
{{- with .Values.rbac.additionalPermissions }}
|
||||||
{{- toYaml . | nindent 2 }}
|
{{- toYaml . | nindent 2 }}
|
||||||
{{- end }}
|
{{- 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 }}
|
{{- end }}
|
||||||
|
@ -13,4 +13,39 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ template "external-dns.serviceAccountName" . }}
|
name: {{ template "external-dns.serviceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
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 }}
|
{{- end }}
|
||||||
|
@ -111,6 +111,9 @@ spec:
|
|||||||
{{- if .Values.namespaced }}
|
{{- if .Values.namespaced }}
|
||||||
- --namespace={{ .Release.Namespace }}
|
- --namespace={{ .Release.Namespace }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Values.gatewayNamespace }}
|
||||||
|
- --gateway-namespace={{ .Values.gatewayNamespace }}
|
||||||
|
{{- end }}
|
||||||
{{- range .Values.domainFilters }}
|
{{- range .Values.domainFilters }}
|
||||||
- --domain-filter={{ . }}
|
- --domain-filter={{ . }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
@ -156,3 +156,238 @@ tests:
|
|||||||
- apiGroups: ["gateway.networking.k8s.io"]
|
- apiGroups: ["gateway.networking.k8s.io"]
|
||||||
resources: ["udproutes"]
|
resources: ["udproutes"]
|
||||||
verbs: ["get","watch","list"]
|
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).
|
# -- if `true`, _ExternalDNS_ will run in a namespaced scope (`Role`` and `Rolebinding`` will be namespaced too).
|
||||||
namespaced: false
|
namespaced: false
|
||||||
|
|
||||||
|
# -- _Gateway API_ gateway namespace to watch.
|
||||||
|
gatewayNamespace: # @schema type:[string, null]; default: null
|
||||||
|
|
||||||
# -- _Kubernetes_ resources to monitor for DNS entries.
|
# -- _Kubernetes_ resources to monitor for DNS entries.
|
||||||
sources:
|
sources:
|
||||||
- service
|
- service
|
||||||
|
Loading…
Reference in New Issue
Block a user