From 2038b2b46cddae65887155bcb0db561325c0106e Mon Sep 17 00:00:00 2001 From: tejassinghbhati Date: Thu, 3 Sep 2026 18:48:58 +0530 Subject: [PATCH] feat(chart): expose automountServiceAccountToken and extra volumes The chart never rendered automountServiceAccountToken, so several Gatekeeper policies reject the workload for leaving it to the cluster default rather than setting it explicitly. There was also no way to add volumes, which is what you need to run without an automounted token. Renders serviceAccount.automountServiceAccountToken on both the ServiceAccount and the pod spec, and adds extraVolumes and extraVolumeMounts. Default stays true so nothing changes for existing installs. Turning it off on its own is not enough to keep the controller working. It authenticates with rest.InClusterConfig(), which wants token, ca.crt and namespace under /var/run/secrets/kubernetes.io/serviceaccount, so all three have to come back through a projected volume. values.yaml carries that example rather than leaving people to work it out. Signed-off-by: tejassinghbhati --- charts/node-readiness-controller/README.md | 3 + .../templates/deployment.yaml | 7 ++ .../templates/serviceaccount.yaml | 1 + .../tests/automount_test.yaml | 106 ++++++++++++++++++ charts/node-readiness-controller/values.yaml | 38 +++++++ 5 files changed, 155 insertions(+) create mode 100644 charts/node-readiness-controller/tests/automount_test.yaml diff --git a/charts/node-readiness-controller/README.md b/charts/node-readiness-controller/README.md index 60eddbfe..12583c31 100644 --- a/charts/node-readiness-controller/README.md +++ b/charts/node-readiness-controller/README.md @@ -77,6 +77,9 @@ The following table lists the configurable parameters of the _node-readiness-con | `serviceAccount.create` | If `true`, create a service account | `true` | | `serviceAccount.name` | The name of the service account to use, if not set and create is true a name is generated using the fullname template | `nil` | | `serviceAccount.annotations` | Specifies custom annotations for the serviceAccount | `{}` | +| `serviceAccount.automountServiceAccountToken` | Whether the API server automounts a ServiceAccount token. Rendered on both the ServiceAccount and the pod spec so Gatekeeper and Pod Security policies see it set explicitly | `true` | +| `extraVolumes` | Additional volumes on the controller pod. Needed to supply a projected token when automounting is disabled | `[]` | +| `extraVolumeMounts` | Additional volume mounts on the controller container | `[]` | | `podAnnotations` | Annotations to add to the node-readiness-controller Pods | `{"kubectl.kubernetes.io/default-container":"manager"}` | | `podLabels` | Labels to add to the node-readiness-controller Pods | `{}` | | `commonLabels` | Labels to apply to all resources | `{}` | diff --git a/charts/node-readiness-controller/templates/deployment.yaml b/charts/node-readiness-controller/templates/deployment.yaml index 22628a7a..b1738f27 100644 --- a/charts/node-readiness-controller/templates/deployment.yaml +++ b/charts/node-readiness-controller/templates/deployment.yaml @@ -23,6 +23,7 @@ spec: {{- end }} spec: serviceAccountName: {{ include "node-readiness-controller.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -109,6 +110,9 @@ spec: mountPath: {{ .Values.metrics.certDir }} readOnly: true {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} volumes: {{- if .Values.webhook.enabled }} - name: cert @@ -121,6 +125,9 @@ spec: secret: secretName: {{ .Values.metrics.certSecretName }} {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/charts/node-readiness-controller/templates/serviceaccount.yaml b/charts/node-readiness-controller/templates/serviceaccount.yaml index 84a4debc..8218b8c6 100644 --- a/charts/node-readiness-controller/templates/serviceaccount.yaml +++ b/charts/node-readiness-controller/templates/serviceaccount.yaml @@ -10,4 +10,5 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} {{- end }} diff --git a/charts/node-readiness-controller/tests/automount_test.yaml b/charts/node-readiness-controller/tests/automount_test.yaml new file mode 100644 index 00000000..2b5ccdc2 --- /dev/null +++ b/charts/node-readiness-controller/tests/automount_test.yaml @@ -0,0 +1,106 @@ +suite: Test ServiceAccount token automounting and extra volumes + +templates: + - "*.yaml" + +release: + name: node-readiness-controller + +tests: + - it: sets automountServiceAccountToken on the ServiceAccount by default + template: templates/serviceaccount.yaml + asserts: + - isKind: + of: ServiceAccount + - equal: + path: automountServiceAccountToken + value: true + + - it: sets automountServiceAccountToken on the pod spec by default + template: templates/deployment.yaml + asserts: + - equal: + path: spec.template.spec.automountServiceAccountToken + value: true + + # Gatekeeper policies care that the field is explicitly false, not absent, + # so assert the rendered value rather than just its absence. + - it: renders false on both objects when automounting is disabled + set: + serviceAccount: + automountServiceAccountToken: false + asserts: + - equal: + path: automountServiceAccountToken + value: false + template: templates/serviceaccount.yaml + - equal: + path: spec.template.spec.automountServiceAccountToken + value: false + template: templates/deployment.yaml + + - it: adds extra volumes and mounts when supplied + template: templates/deployment.yaml + set: + extraVolumes: + - name: sa-token + projected: + sources: + - serviceAccountToken: + path: token + expirationSeconds: 3600 + extraVolumeMounts: + - name: sa-token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + readOnly: true + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: sa-token + projected: + sources: + - serviceAccountToken: + path: token + expirationSeconds: 3600 + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: sa-token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + readOnly: true + + # The chart already mounts webhook and metrics certificates, so the extra + # entries have to be additive rather than replacing them. + - it: keeps the cert volumes alongside extra volumes + template: templates/deployment.yaml + set: + webhook: + enabled: true + extraVolumes: + - name: sa-token + emptyDir: {} + extraVolumeMounts: + - name: sa-token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: cert + secret: + secretName: webhook-server-certs + defaultMode: 420 + - contains: + path: spec.template.spec.volumes + content: + name: sa-token + emptyDir: {} + + # volumes is rendered unconditionally by the template, so it is present but + # empty when nothing opts in. + - it: renders no extra volumes by default + template: templates/deployment.yaml + asserts: + - isNullOrEmpty: + path: spec.template.spec.volumes diff --git a/charts/node-readiness-controller/values.yaml b/charts/node-readiness-controller/values.yaml index 4a348e0c..d347bb3f 100644 --- a/charts/node-readiness-controller/values.yaml +++ b/charts/node-readiness-controller/values.yaml @@ -86,6 +86,12 @@ serviceAccount: create: true name: "" annotations: {} + # -- Whether the API server should automount a ServiceAccount token. Rendered on + # the ServiceAccount and on the pod spec, since Gatekeeper and Pod Security + # policies commonly require it to be set explicitly rather than left to the + # cluster default. Set false and supply a projected token through extraVolumes + # if your policy forbids automounting. + automountServiceAccountToken: true # Enable leader election to support multiple replicas leaderElection: @@ -163,6 +169,38 @@ validatingWebhook: nodeSelector: {} +# -- Additional volumes on the controller pod. +# The controller authenticates with rest.InClusterConfig(), which needs a token, +# ca.crt and namespace under /var/run/secrets/kubernetes.io/serviceaccount. When +# serviceAccount.automountServiceAccountToken is false you have to provide all +# three yourself, for example: +# +# extraVolumes: +# - name: sa-token +# projected: +# sources: +# - serviceAccountToken: +# path: token +# expirationSeconds: 3600 +# - configMap: +# name: kube-root-ca.crt +# items: +# - key: ca.crt +# path: ca.crt +# - downwardAPI: +# items: +# - path: namespace +# fieldRef: +# fieldPath: metadata.namespace +# extraVolumeMounts: +# - name: sa-token +# mountPath: /var/run/secrets/kubernetes.io/serviceaccount +# readOnly: true +extraVolumes: [] + +# -- Additional volume mounts on the controller container. +extraVolumeMounts: [] + tolerations: - effect: NoSchedule operator: Exists