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