Skip to content
Open
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: 4 additions & 0 deletions charts/external-dns/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Default `provider.webhook.securityContext` to no privilege escalation, no capabilities and a read-only root filesystem, like the `external-dns` container, so the `Pod` meets the _restricted_ Pod Security Standard. [#6785](https://github.com/kubernetes-sigs/external-dns/pull/6785) @LorbusChris

### Fixed

- Mount a projected `ServiceAccount` token into the `external-dns` container when `automountServiceAccountToken` is `false`, so the `Pod` no longer crashes without API credentials. [#6814](https://github.com/kubernetes-sigs/external-dns/pull/6814) @ashokpariya0

## [v1.23.0] - 2026-10-01

### Changed
Expand Down
2 changes: 1 addition & 1 deletion charts/external-dns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ If `namespaced` is set to `true`, please ensure that `sources` only contains sup
| affinity | object | `{}` | Affinity settings for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided for pod affinity or pod anti-affinity one will be created from the pod selector labels. |
| annotationFilter | string | `nil` | Filter resources queried for endpoints by annotation selector. |
| annotationPrefix | string | `nil` | Annotation prefix for external-dns annotations (useful for split horizon DNS with multiple instances). |
| automountServiceAccountToken | bool | `true` | Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`. |
| automountServiceAccountToken | bool | `true` | Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`. As _ExternalDNS_ needs the Kubernetes API, the chart then mounts a projected `ServiceAccount` token into the `external-dns` container only, unless `extraVolumeMounts` already mounts `/var/run/secrets/kubernetes.io/serviceaccount`. |
| commonLabels | object | `{}` | Labels to add to all chart resources. |
| deploymentAnnotations | object | `{}` | Annotations to add to the `Deployment`. |
| deploymentStrategy | object | `{"type":"Recreate"}` | [Deployment Strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). |
Expand Down
38 changes: 36 additions & 2 deletions charts/external-dns/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{{- $defaultSelector := (include "external-dns.labelSelector" $ ) | fromYaml -}}
{{- $providerName := tpl (include "external-dns.providerName" .) $ }}
{{- /* ExternalDNS always needs the Kubernetes API. With automounting disabled, mount the token
into the external-dns container only (not the webhook sidecar), unless the user already
mounts that path through extraVolumeMounts. */}}
Comment on lines +3 to +5

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extraVolumeMounts part restates the loop below.

Suggested change
{{- /* ExternalDNS always needs the Kubernetes API. With automounting disabled, mount the token
into the external-dns container only (not the webhook sidecar), unless the user already
mounts that path through extraVolumeMounts. */}}
{{- /* ExternalDNS always needs the API: mount the token into the external-dns container only, not the webhook sidecar. */}}

{{- $tokenMountPath := "/var/run/secrets/kubernetes.io/serviceaccount" }}
{{- $mountToken := and (kindIs "bool" .Values.automountServiceAccountToken) (not .Values.automountServiceAccountToken) }}
{{- range .Values.extraVolumeMounts }}
{{- if eq (toString .mountPath) $tokenMountPath }}
{{- $mountToken = false }}
{{- end }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -187,8 +197,13 @@ spec:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumeMounts }}
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumeMounts $mountToken }}
volumeMounts:
{{- if $mountToken }}
- name: kube-api-access
mountPath: {{ $tokenMountPath }}
readOnly: true
{{- end }}
{{- if .Values.secretConfiguration.enabled }}
- name: secrets
mountPath: {{ tpl .Values.secretConfiguration.mountPath $ }}
Expand Down Expand Up @@ -241,8 +256,27 @@ spec:
{{- end }}
{{- end }}
{{- end }}
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumes }}
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumes $mountToken }}
volumes:
{{- if $mountToken }}
- name: kube-api-access
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3607

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3607 looks arbitrary, but it is the value the ServiceAccount admission plugin injects (WarnOnlyBoundTokenExpirationSeconds), and the API server extends exactly this value.
Could you add a short comment so nobody "fixes" it to 3600?

Suggested change
expirationSeconds: 3607
{{- /* 3607 like the auto-mounted token: the API server extends this exact value. */}}
expirationSeconds: 3607

- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
{{- end }}
{{- if .Values.secretConfiguration.enabled }}
- name: secrets
secret:
Expand Down
118 changes: 118 additions & 0 deletions charts/external-dns/tests/deployment-serviceaccount-token_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
suite: Deployment service account token
set:
policy: upsert-only
templates:
- deployment.yaml
release:
namespace: default
tests:
- it: should not add a token volume by default
asserts:
- equal:
path: spec.template.spec.automountServiceAccountToken
value: true
- notExists:
path: spec.template.spec.volumes
- notExists:
path: spec.template.spec.containers[?(@.name == "external-dns")].volumeMounts

- it: should mount a projected token when automountServiceAccountToken is false
set:
automountServiceAccountToken: false
asserts:
- equal:
path: spec.template.spec.automountServiceAccountToken
value: false
- contains:
path: spec.template.spec.containers[?(@.name == "external-dns")].volumeMounts
content:
name: kube-api-access
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
- contains:
path: spec.template.spec.volumes
content:
name: kube-api-access
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3607
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace

- it: should keep secret and extra volumes next to the token volume
set:
automountServiceAccountToken: false
secretConfiguration:
enabled: true
mountPath: /etc/secrets
data:
key: value
extraVolumes:
- name: extra
emptyDir: {}
extraVolumeMounts:
- name: extra
mountPath: /extra
asserts:
- lengthEqual:
path: spec.template.spec.volumes
count: 3
- lengthEqual:
path: spec.template.spec.containers[?(@.name == "external-dns")].volumeMounts
count: 3

- it: should not mount the token into the webhook sidecar
set:
automountServiceAccountToken: false
provider:
name: webhook
webhook:
image:
repository: example/webhook
tag: v1.0.0
asserts:
- contains:
path: spec.template.spec.containers[?(@.name == "external-dns")].volumeMounts
content:
name: kube-api-access
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
- notExists:
path: spec.template.spec.containers[?(@.name == "webhook")].volumeMounts

- it: should not add a token volume when extraVolumeMounts already mounts the token path
set:
automountServiceAccountToken: false
extraVolumes:
- name: my-token
projected:
sources:
- serviceAccountToken:
path: token
extraVolumeMounts:
- name: my-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
asserts:
- lengthEqual:
path: spec.template.spec.volumes
count: 1
- notContains:
path: spec.template.spec.volumes
any: true
content:
name: kube-api-access
- lengthEqual:
path: spec.template.spec.containers[?(@.name == "external-dns")].volumeMounts
count: 1
2 changes: 1 addition & 1 deletion charts/external-dns/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
]
},
"automountServiceAccountToken": {
"description": "Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`.",
"description": "Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`. As _ExternalDNS_ needs the Kubernetes API, the chart then mounts a projected `ServiceAccount` token into the `external-dns` container only, unless `extraVolumeMounts` already mounts `/var/run/secrets/kubernetes.io/serviceaccount`.",
"type": "boolean"
},
"commonLabels": {
Expand Down
2 changes: 1 addition & 1 deletion charts/external-dns/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ podLabels: {}
# -- Annotations to add to the `Pod`.
podAnnotations: {}

# -- (bool) Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`.
# -- (bool) Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`. As _ExternalDNS_ needs the Kubernetes API, the chart then mounts a projected `ServiceAccount` token into the `external-dns` container only, unless `extraVolumeMounts` already mounts `/var/run/secrets/kubernetes.io/serviceaccount`.
automountServiceAccountToken: true

# -- If `true`, the `Pod` will have [process namespace sharing](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/) enabled.
Expand Down
Loading