diff --git a/chart/files/pod-template-file.kubernetes-helm-yaml b/chart/files/pod-template-file.kubernetes-helm-yaml index 679b1ba451559..3fa53f1e5cc72 100644 --- a/chart/files/pod-template-file.kubernetes-helm-yaml +++ b/chart/files/pod-template-file.kubernetes-helm-yaml @@ -21,7 +21,8 @@ {{- $affinity := or .Values.workers.affinity .Values.affinity }} {{- $tolerations := or .Values.workers.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.workers.topologySpreadConstraints .Values.topologySpreadConstraints }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.workers) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.workers) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.workers) }} apiVersion: v1 kind: Pod metadata: @@ -62,6 +63,7 @@ spec: {{- include "container_extra_envs" (list . .Values.workers.env) | indent 6 }} image: {{ template "pod_template_image" . }} imagePullPolicy: {{ .Values.images.pod_template.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 8 }} name: base resources: {{- toYaml .Values.workers.resources | nindent 8 }} volumeMounts: diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt index 63b88264e6786..57e8c9da52b24 100644 --- a/chart/templates/NOTES.txt +++ b/chart/templates/NOTES.txt @@ -175,6 +175,14 @@ DEPRECATION WARNING: {{- if not (or .Values.webserverSecretKey .Values.webserverSecretKeySecretName) }} +{{- if .Values.securityContext }} + + DEPRECATION WARNING: + `securityContext` has been renamed to `securityContexts`, to be enabled on container and pod level. + Please change your values as support for the old name will be dropped in a future release. + +{{- end }} + ########################################################### # WARNING: You should set a static webserver secret key # ########################################################### diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml index 25ae08d9cb77f..10d90c091fd40 100644 --- a/chart/templates/_helpers.yaml +++ b/chart/templates/_helpers.yaml @@ -173,7 +173,7 @@ If release name contains chart name it will be used as a full name. - name: {{ .Values.dags.gitSync.containerName }}{{ if .is_init }}-init{{ end }} image: {{ template "git_sync_image" . }} imagePullPolicy: {{ .Values.images.gitSync.pullPolicy }} - securityContext: {{- include "localSecurityContext" .Values.dags.gitSync | nindent 4 }} + securityContext: {{- include "localContainerSecurityContext" .Values.dags.gitSync | nindent 4 }} env: {{- if .Values.dags.gitSync.sshKeySecret }} - name: GIT_SSH_KEY_FILE @@ -731,29 +731,33 @@ server_tls_key_file = /etc/pgbouncer/server.key {{- end }} {{/* -Set the default value for securityContext -If no value is passed for securityContext or .securityContext, defaults to global uid and gid. +Set the default value for pod securityContext +If no value is passed for securityContexts.pod or .securityContexts.pod or legacy securityContext and .securityContext, defaults to global uid and gid. - +------------------------+ +-----------------+ +-------------------------+ - | .securityContext | -> | securityContext | -> | Values.uid + Values.gid | - +------------------------+ +-----------------+ +-------------------------+ + +-----------------------------+ +------------------------+ +----------------------+ +-----------------+ +-------------------------+ + | .securityContexts.pod | -> | .securityContext | -> | securityContexts.pod | -> | securityContext | -> | Values.uid + Values.gid | + +-----------------------------+ +------------------------+ +----------------------+ +-----------------+ +-------------------------+ -Values are not accumulated meaning that if runAsUser is set to 10 in .securityContext, +Values are not accumulated meaning that if runAsUser is set to 10 in .securityContexts.pod, any extra values set to securityContext or uid+gid will be ignored. The template can be called like so: - include "airflowSecurityContext" (list . .Values.webserver) + include "airflowPodSecurityContext" (list . .Values.webserver) Where `.` is the global variables scope and `.Values.webserver` the local variables scope for the webserver template. */}} -{{- define "airflowSecurityContext" -}} - {{- $ := index . 0 }} +{{- define "airflowPodSecurityContext" -}} + {{- $ := index . 0 -}} {{- with index . 1 }} - {{- if .securityContext }} - {{- toYaml .securityContext }} - {{- else if $.Values.securityContext }} - {{- toYaml $.Values.securityContext }} - {{- else }} + {{- if .securityContexts.pod -}} + {{ toYaml .securityContexts.pod | print }} + {{- else if .securityContext -}} + {{ toYaml .securityContext | print }} + {{- else if $.Values.securityContexts.pod -}} + {{ toYaml $.Values.securityContexts.pod | print }} + {{- else if $.Values.securityContext -}} + {{ toYaml $.Values.securityContext | print }} + {{- else -}} runAsUser: {{ $.Values.uid }} fsGroup: {{ $.Values.gid }} {{- end }} @@ -761,55 +765,114 @@ fsGroup: {{ $.Values.gid }} {{- end }} {{/* -Set the default value for securityContext -If no value is passed for securityContext or .securityContext, defaults to UID in the local node. +Set the default value for pod securityContext +If no value is passed for .securityContexts.pod or .securityContext, defaults to UID in the local node. - +------------------------+ +-------------+ - | .securityContext | > | .uid | - +------------------------+ +-------------+ + +-----------------------------+ +------------------------+ +-------------+ + | .securityContexts.pod | -> | .securityContext | -> | .uid | + +-----------------------------+ +------------------------+ +-------------+ The template can be called like so: - include "localSecurityContext" .Values.statsd + include "localPodSecurityContext" (list . .Values.schedule) It is important to pass the local variables scope to this template as it is used to determine the local node value for uid. */}} -{{- define "localSecurityContext" -}} - {{- if .securityContext }} - {{- toYaml .securityContext }} - {{- else }} - {{- printf "runAsUser: %v" .uid }} - {{- end }} -{{- end }} +{{- define "localPodSecurityContext" -}} + {{- if .securityContexts.pod -}} + {{ toYaml .securityContexts.pod | print }} + {{- else if .securityContext -}} + {{ toYaml .securityContext | print }} + {{- else -}} +runAsUser: {{ .uid }} + {{- end -}} +{{- end -}} + +{{/* +Set the default value for container securityContext +If no value is passed for .securityContexts.container or .securityContext, defaults to UID in the local node. + + +-----------------------------------+ +------------------------+ +-------------+ + | .securityContexts.container | -> | .securityContext | -> | .uid | + +-----------------------------------+ +------------------------+ +-------------+ + +The template can be called like so: + include "localContainerSecurityContext" .Values.statsd + +It is important to pass the local variables scope to this template as it is used to determine the local node value for uid. +*/}} +{{- define "localContainerSecurityContext" -}} + {{- if .securityContexts.container -}} + {{ toYaml .securityContexts.container | print }} + {{- else if .securityContext -}} + {{ toYaml .securityContext | print }} + {{- else -}} +runAsUser: {{ .uid }} + {{- end -}} +{{- end -}} {{/* Set the default value for workers chown for persistent storage -If no value is passed for securityContext or .securityContext, defaults to global uid and gid. +If no value is passed for securityContexts.pod or .securityContexts.pod or legacy securityContext and .securityContext, defaults to global uid and gid. The template looks for `runAsUser` and `fsGroup` specifically, any other parameter will be ignored. - +------------------------+ +-----------------+ +-------------------------+ - | .securityContext | -> | securityContext | -> | Values.uid + Values.gid | - +------------------------+ +-----------------+ +-------------------------+ + +-----------------------------+ +----------------------------------------------------+ +------------------+ +-------------------------+ + | .securityContexts.pod | -> | securityContexts.pod | .securityContexts.pod | -> | securityContexts | -> | Values.uid + Values.gid | + +-----------------------------+ +----------------------------------------------------+ +------------------+ +-------------------------+ -Values are not accumulated meaning that if runAsUser is set to 10 in .securityContext, -any extra values set to securityContext or uid+gid will be ignored. +Values are not accumulated meaning that if runAsUser is set to 10 in .securityContexts.pod, +any extra values set to securityContexts or uid+gid will be ignored. The template can be called like so: - include "airflowSecurityContextIds" (list . .Values.workers) + include "airflowPodSecurityContextsIds" (list . .Values.webserver) Where `.` is the global variables scope and `.Values.workers` the local variables scope for the workers template. */}} -{{- define "airflowSecurityContextIds" -}} - {{- $ := index . 0 }} +{{- define "airflowPodSecurityContextsIds" -}} + {{- $ := index . 0 -}} + {{- with index . 1 }} + {{- if .securityContexts.pod -}} + {{ pluck "runAsUser" .securityContexts.pod | first | default $.Values.uid }}:{{ pluck "fsGroup" .securityContexts.pod | first | default $.Values.gid }} + {{- else if $.Values.securityContext -}} + {{ pluck "runAsUser" $.Values.securityContext | first | default $.Values.uid }}:{{ pluck "fsGroup" $.Values.securityContext | first | default $.Values.gid }} + {{- else if $.Values.securityContexts.pod -}} + {{ pluck "runAsUser" $.Values.securityContexts.pod | first | default $.Values.uid }}:{{ pluck "fsGroup" $.Values.securityContexts.pod | first | default $.Values.gid }} + {{- else if $.Values.securityContext -}} + {{ pluck "runAsUser" $.Values.securityContext | first | default $.Values.uid }}:{{ pluck "fsGroup" $.Values.securityContext | first | default $.Values.gid }} + {{- else -}} +{{ $.Values.uid }}:{{ $.Values.gid }} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Set the default value for container securityContext +If no value is passed for securityContexts.container or .securityContexts.container, defaults to deny privileges escallation and dropping all POSIX capabilities. + + +-----------------------------------+ +----------------------------+ +-----------------------------------------------------------+ + | .securityContexts.container | -> | securityContexts.containers | -> | allowPrivilegesEscalation: false, capabilities.drop: [ALL]| + +-----------------------------------+ +----------------------------+ +-----------------------------------------------------------+ + + +The template can be called like so: + include "containerSecurityContext" (list . .Values.statsd) + +Where `.` is the global variables scope and `.Values.webserver` the local variables scope for the webserver template. +*/}} +{{- define "containerSecurityContext" -}} + {{- $ := index . 0 -}} {{- with index . 1 }} - {{- if .securityContext }} - {{- pluck "runAsUser" .securityContext | first | default $.Values.uid }}:{{ pluck "fsGroup" .securityContext | first | default $.Values.gid }} - {{- else if $.Values.securityContext }} - {{- pluck "runAsUser" $.Values.securityContext | first | default $.Values.uid }}:{{ pluck "fsGroup" $.Values.securityContext | first | default $.Values.gid }} - {{- else }} - {{- printf "%s:%s" $.Values.uid $.Values.gid }} - {{- end }} - {{- end }} -{{- end }} + {{- if .securityContexts.container -}} + {{ toYaml .securityContexts.container | print }} + {{- else if $.Values.securityContexts.containers -}} + {{ toYaml $.Values.securityContexts.containers | print }} + {{- else -}} +allowPrivilegeEscalation: false +capabilities: + drop: + - ALL + {{- end -}} + {{- end -}} +{{- end -}} {{- define "container_extra_envs" -}} {{- $ := index . 0 -}} diff --git a/chart/templates/cleanup/cleanup-cronjob.yaml b/chart/templates/cleanup/cleanup-cronjob.yaml index 1dab5ca0cb5a2..880f9e9589914 100644 --- a/chart/templates/cleanup/cleanup-cronjob.yaml +++ b/chart/templates/cleanup/cleanup-cronjob.yaml @@ -25,7 +25,7 @@ {{- $affinity := or .Values.cleanup.affinity .Values.affinity }} {{- $tolerations := or .Values.cleanup.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.cleanup.topologySpreadConstraints .Values.topologySpreadConstraints }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.cleanup) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.cleanup) }} {{- if semverCompare ">= 1.21.x" (include "kubeVersion" .) }} apiVersion: batch/v1 {{- else }} diff --git a/chart/templates/dag-processor/dag-processor-deployment.yaml b/chart/templates/dag-processor/dag-processor-deployment.yaml index dad46c2b5fac3..33782a6e855fe 100644 --- a/chart/templates/dag-processor/dag-processor-deployment.yaml +++ b/chart/templates/dag-processor/dag-processor-deployment.yaml @@ -27,7 +27,8 @@ {{- $tolerations := or .Values.dagProcessor.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.dagProcessor.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.dagProcessor.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.dagProcessor) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.dagProcessor) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.dagProcessor) }} kind: Deployment apiVersion: apps/v1 metadata: @@ -142,6 +143,7 @@ spec: - name: dag-processor image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.dagProcessor.command }} command: {{ tpl (toYaml .Values.dagProcessor.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/flower/flower-deployment.yaml b/chart/templates/flower/flower-deployment.yaml index 1ffb2cea76148..418a5f51c3749 100644 --- a/chart/templates/flower/flower-deployment.yaml +++ b/chart/templates/flower/flower-deployment.yaml @@ -27,7 +27,8 @@ {{- $tolerations := or .Values.flower.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.flower.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.flower.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.flower) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.flower) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.flower) }} kind: Deployment apiVersion: apps/v1 metadata: @@ -88,6 +89,7 @@ spec: - name: flower image: {{ template "flower_image" . }} imagePullPolicy: {{ .Values.images.flower.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.flower.command }} command: {{ tpl (toYaml .Values.flower.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/jobs/create-user-job.yaml b/chart/templates/jobs/create-user-job.yaml index 8d2c796bc9d1b..9ac510c2bad59 100644 --- a/chart/templates/jobs/create-user-job.yaml +++ b/chart/templates/jobs/create-user-job.yaml @@ -25,7 +25,8 @@ {{- $affinity := or .Values.createUserJob.affinity .Values.affinity }} {{- $tolerations := or .Values.createUserJob.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.createUserJob.topologySpreadConstraints .Values.topologySpreadConstraints }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.createUserJob) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.createUserJob) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.createUserJob) }} apiVersion: batch/v1 kind: Job metadata: @@ -86,6 +87,7 @@ spec: - name: create-user image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.createUserJob.command }} command: {{ tpl (toYaml .Values.createUserJob.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/jobs/migrate-database-job.yaml b/chart/templates/jobs/migrate-database-job.yaml index f3c869f506efd..30dda11b5b8d3 100644 --- a/chart/templates/jobs/migrate-database-job.yaml +++ b/chart/templates/jobs/migrate-database-job.yaml @@ -25,7 +25,8 @@ {{- $affinity := or .Values.migrateDatabaseJob.affinity .Values.affinity }} {{- $tolerations := or .Values.migrateDatabaseJob.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.migrateDatabaseJob.topologySpreadConstraints .Values.topologySpreadConstraints }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.migrateDatabaseJob) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.migrateDatabaseJob) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.migrateDatabaseJob) }} apiVersion: batch/v1 kind: Job metadata: @@ -86,6 +87,7 @@ spec: - name: run-airflow-migrations image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.migrateDatabaseJob.command }} command: {{- tpl (toYaml .Values.migrateDatabaseJob.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/pgbouncer/pgbouncer-deployment.yaml b/chart/templates/pgbouncer/pgbouncer-deployment.yaml index c78fa9da4586d..998339720576c 100644 --- a/chart/templates/pgbouncer/pgbouncer-deployment.yaml +++ b/chart/templates/pgbouncer/pgbouncer-deployment.yaml @@ -26,6 +26,8 @@ {{- $tolerations := or .Values.pgbouncer.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.pgbouncer.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.pgbouncer.revisionHistoryLimit .Values.revisionHistoryLimit }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.pgbouncer) }} +{{- $containerSecurityContextMetricsExporter := include "containerSecurityContext" (list . .Values.pgbouncer.metricsExporterSidecar) }} kind: Deployment apiVersion: apps/v1 metadata: @@ -91,6 +93,7 @@ spec: - name: pgbouncer image: {{ template "pgbouncer_image" . }} imagePullPolicy: {{ .Values.images.pgbouncer.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.pgbouncer.command }} command: {{ tpl (toYaml .Values.pgbouncer.command) . | nindent 12 }} {{- end }} @@ -149,6 +152,7 @@ spec: resources: {{- toYaml .Values.pgbouncer.metricsExporterSidecar.resources | nindent 12 }} image: {{ template "pgbouncer_exporter_image" . }} imagePullPolicy: {{ .Values.images.pgbouncerExporter.pullPolicy }} + securityContext: {{ $containerSecurityContextMetricsExporter | nindent 12 }} env: - name: DATABASE_URL valueFrom: diff --git a/chart/templates/redis/redis-statefulset.yaml b/chart/templates/redis/redis-statefulset.yaml index a6896a271b73f..f83658d9436f2 100644 --- a/chart/templates/redis/redis-statefulset.yaml +++ b/chart/templates/redis/redis-statefulset.yaml @@ -25,7 +25,8 @@ {{- $affinity := or .Values.redis.affinity .Values.affinity }} {{- $tolerations := or .Values.redis.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.redis.topologySpreadConstraints .Values.topologySpreadConstraints }} -{{- $securityContext := include "localSecurityContext" .Values.redis }} +{{- $securityContext := include "localPodSecurityContext" .Values.redis }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.redis) }} kind: StatefulSet apiVersion: apps/v1 metadata: @@ -79,6 +80,7 @@ spec: - name: redis image: {{ template "redis_image" . }} imagePullPolicy: {{ .Values.images.redis.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} command: ["/bin/sh"] resources: {{- toYaml .Values.redis.resources | nindent 12 }} args: ["-c", "redis-server --requirepass ${REDIS_PASSWORD}"] diff --git a/chart/templates/scheduler/scheduler-deployment.yaml b/chart/templates/scheduler/scheduler-deployment.yaml index d10e13414324f..de6f2dba54f9f 100644 --- a/chart/templates/scheduler/scheduler-deployment.yaml +++ b/chart/templates/scheduler/scheduler-deployment.yaml @@ -37,7 +37,10 @@ {{- $tolerations := or .Values.scheduler.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.scheduler.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.scheduler.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.scheduler) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.scheduler) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.scheduler) }} +{{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.scheduler.waitForMigrations) }} +{{- $containerSecurityContextLogGroomerSidecar := include "containerSecurityContext" (list . .Values.scheduler.logGroomerSidecar) }} kind: {{ if $stateful }}StatefulSet{{ else }}Deployment{{ end }} apiVersion: apps/v1 metadata: @@ -136,6 +139,7 @@ spec: resources: {{- toYaml .Values.scheduler.resources | nindent 12 }} image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -167,6 +171,7 @@ spec: - name: scheduler image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.scheduler.command }} command: {{ tpl (toYaml .Values.scheduler.command) . | nindent 12 }} {{- end }} @@ -227,6 +232,7 @@ spec: resources: {{- toYaml .Values.scheduler.logGroomerSidecar.resources | nindent 12 }} image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextLogGroomerSidecar | nindent 12 }} {{- if .Values.scheduler.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.scheduler.logGroomerSidecar.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/statsd/statsd-deployment.yaml b/chart/templates/statsd/statsd-deployment.yaml index 8922c0d250da6..14b5abfbfd74e 100644 --- a/chart/templates/statsd/statsd-deployment.yaml +++ b/chart/templates/statsd/statsd-deployment.yaml @@ -26,7 +26,8 @@ {{- $tolerations := or .Values.statsd.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.statsd.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.statsd.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "localSecurityContext" .Values.statsd }} +{{- $securityContext := include "localPodSecurityContext" .Values.statsd }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.statsd) }} kind: Deployment apiVersion: apps/v1 metadata: @@ -88,8 +89,12 @@ spec: - name: statsd image: {{ template "statsd_image" . }} imagePullPolicy: {{ .Values.images.statsd.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.statsd.args }} args: {{ tpl (toYaml .Values.statsd.args) . | nindent 12 }} + {{- else}} + args: + - "--statsd.mapping-config=/etc/statsd-exporter/mappings.yml" {{- end }} resources: {{- toYaml .Values.statsd.resources | nindent 12 }} ports: diff --git a/chart/templates/triggerer/triggerer-deployment.yaml b/chart/templates/triggerer/triggerer-deployment.yaml index b690c606f1f08..3515794f7491c 100644 --- a/chart/templates/triggerer/triggerer-deployment.yaml +++ b/chart/templates/triggerer/triggerer-deployment.yaml @@ -29,7 +29,10 @@ {{- $tolerations := or .Values.triggerer.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.triggerer.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.triggerer.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.triggerer) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.triggerer) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.triggerer) }} +{{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.triggerer.waitForMigrations) }} +{{- $containerSecurityContextLogGroomer := include "containerSecurityContext" (list . .Values.triggerer.logGroomerSidecar) }} kind: {{ if $persistence }}StatefulSet{{ else }}Deployment{{ end }} apiVersion: apps/v1 metadata: @@ -124,6 +127,7 @@ spec: {{- toYaml .Values.triggerer.resources | nindent 12 }} image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -154,6 +158,7 @@ spec: - name: triggerer image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.triggerer.command }} command: {{ tpl (toYaml .Values.triggerer.command) . | nindent 12 }} {{- end }} @@ -208,6 +213,7 @@ spec: resources: {{- toYaml .Values.triggerer.logGroomerSidecar.resources | nindent 12 }} image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextLogGroomer | nindent 12 }} {{- if .Values.triggerer.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.triggerer.logGroomerSidecar.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/webserver/webserver-deployment.yaml b/chart/templates/webserver/webserver-deployment.yaml index 1aefdf121c856..06d7f2640daa7 100644 --- a/chart/templates/webserver/webserver-deployment.yaml +++ b/chart/templates/webserver/webserver-deployment.yaml @@ -25,7 +25,9 @@ {{- $tolerations := or .Values.webserver.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.webserver.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.webserver.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.webserver) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.webserver) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.webserver) }} +{{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.webserver.waitForMigrations) }} kind: Deployment apiVersion: apps/v1 metadata: @@ -131,6 +133,7 @@ spec: resources: {{- toYaml .Values.webserver.resources | nindent 12 }} image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -161,6 +164,7 @@ spec: - name: webserver image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ or $containerSecurityContext .Values.webserver.securityContexts.container .Values.securityContexts.container | nindent 12 }} {{- if .Values.webserver.command }} command: {{ tpl (toYaml .Values.webserver.command) . | nindent 12 }} {{- end }} diff --git a/chart/templates/workers/worker-deployment.yaml b/chart/templates/workers/worker-deployment.yaml index b222ab26156c0..d1e3c0e49ac9a 100644 --- a/chart/templates/workers/worker-deployment.yaml +++ b/chart/templates/workers/worker-deployment.yaml @@ -28,7 +28,12 @@ {{- $tolerations := or .Values.workers.tolerations .Values.tolerations }} {{- $topologySpreadConstraints := or .Values.workers.topologySpreadConstraints .Values.topologySpreadConstraints }} {{- $revisionHistoryLimit := or .Values.workers.revisionHistoryLimit .Values.revisionHistoryLimit }} -{{- $securityContext := include "airflowSecurityContext" (list . .Values.workers) }} +{{- $securityContext := include "airflowPodSecurityContext" (list . .Values.workers) }} +{{- $containerSecurityContext := include "containerSecurityContext" (list . .Values.workers) }} +{{- $containerSecurityContextPersistence := include "containerSecurityContext" (list . .Values.workers.persistence) }} +{{- $containerSecurityContextWaitForMigrations := include "containerSecurityContext" (list . .Values.workers.waitForMigrations) }} +{{- $containerSecurityContextLogGroomerSidecar := include "containerSecurityContext" (list . .Values.workers.logGroomerSidecar) }} +{{- $containerSecurityContextKerberosSidecar := include "containerSecurityContext" (list . .Values.workers.kerberosSidecar) }} kind: {{ if $persistence }}StatefulSet{{ else }}Deployment{{ end }} apiVersion: apps/v1 metadata: @@ -133,10 +138,9 @@ spec: command: - chown - -R - - "{{ include "airflowSecurityContextIds" (list . .Values.workers) }}" + - "{{ include "airflowPodSecurityContextsIds" (list . .Values.workers) }}" - {{ template "airflow_logs" . }} - securityContext: - runAsUser: 0 + securityContext: {{ $containerSecurityContextPersistence | nindent 12 }} volumeMounts: - name: logs mountPath: {{ template "airflow_logs" . }} @@ -146,6 +150,7 @@ spec: resources: {{- toYaml .Values.workers.resources | nindent 12 }} image: {{ template "airflow_image_for_migrations" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextWaitForMigrations | nindent 12 }} volumeMounts: {{- include "airflow_config_mount" . | nindent 12 }} {{- if .Values.volumeMounts }} @@ -176,6 +181,7 @@ spec: - name: worker image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContext | nindent 12 }} {{- if .Values.workers.command }} command: {{ tpl (toYaml .Values.workers.command) . | nindent 12 }} {{- end }} @@ -252,6 +258,7 @@ spec: - name: worker-log-groomer image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextLogGroomerSidecar | nindent 12 }} {{- if .Values.workers.logGroomerSidecar.command }} command: {{ tpl (toYaml .Values.workers.logGroomerSidecar.command) . | nindent 12 }} {{- end }} @@ -281,6 +288,7 @@ spec: - name: worker-kerberos image: {{ template "airflow_image" . }} imagePullPolicy: {{ .Values.images.airflow.pullPolicy }} + securityContext: {{ $containerSecurityContextKerberosSidecar | nindent 12 }} args: ["kerberos"] resources: {{- toYaml .Values.workers.kerberosSidecar.resources | nindent 12 }} volumeMounts: diff --git a/chart/values.schema.json b/chart/values.schema.json index 005948802346a..5897f34639061 100644 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -96,7 +96,7 @@ "x-docsSection": "Common" }, "securityContext": { - "description": "Pod security context definition. The values in this parameter will be used when `securityContext` is not defined for specific Pods", + "description": "Default pod security context definition (deprecated, use `securityContexts` instead). The values in this parameter will be used when `securityContext` is not defined for specific Pods", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -109,6 +109,39 @@ } ] }, + "securityContexts": { + "description": "Default security context definition. The values in this parameter will be used when `securityContexts` is not defined for specific Pods/Container.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Default pod security context definition. The values in this parameter will be used when `securityContexts` is not defined for specific Pods.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Default container security context definition. The values in this parameter will be used when `securityContexts` is not defined for specific containers", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false + } + ] + } + } + }, "nodeSelector": { "description": "Select certain nodes for all pods.", "type": "object", @@ -1444,6 +1477,30 @@ "additionalProperties": { "type": "string" } + }, + "securityContexts": { + "description": "Security context definition for the persistence. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the persistence.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -1474,6 +1531,30 @@ } ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "securityContexts": { + "description": "Security context definition for the kerberos sidecar. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the kerberos sidecar.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -1625,10 +1706,10 @@ }, "logGroomerSidecar": { "$ref": "#/definitions/logGroomerConfigType", - "description": "Configuration for log groomer sidecar" + "description": "Configuration for worker log groomer sidecar" }, "securityContext": { - "description": "Security context for the worker pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the worker pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -1640,6 +1721,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the workers. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the workers.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the workers.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "waitForMigrations": { "description": "wait-for-airflow-migrations init container.", "type": "object", @@ -1670,6 +1789,30 @@ ], "additionalProperties": false } + }, + "securityContexts": { + "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the wait for migrations.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -2003,10 +2146,10 @@ }, "logGroomerSidecar": { "$ref": "#/definitions/logGroomerConfigType", - "description": "Configuration for log groomer sidecar" + "description": "Configuration for the schedulers log groomer sidecar." }, "securityContext": { - "description": "Security context for the scheduler pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the scheduler pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -2018,6 +2161,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the scheduler. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the scheduler.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the scheduler.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "waitForMigrations": { "description": "wait-for-airflow-migrations init container.", "type": "object", @@ -2048,6 +2229,30 @@ ], "additionalProperties": false } + }, + "securityContexts": { + "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the wait for migrations.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -2377,7 +2582,7 @@ } }, "securityContext": { - "description": "Security context for the triggerer pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the triggerer pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -2389,6 +2594,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the triggerer. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the triggerer.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the triggerer.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "logGroomerSidecar": { "$ref": "#/definitions/logGroomerConfigType", "description": "Configuration for log groomer sidecar" @@ -2423,6 +2666,30 @@ ], "additionalProperties": false } + }, + "securityContexts": { + "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the wait for migrations.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -2698,7 +2965,7 @@ } }, "securityContext": { - "description": "Security context for the dag processor pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the dag processor pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -2710,6 +2977,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the dag processor. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the dag processor.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the dag processor.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "logGroomerSidecar": { "$ref": "#/definitions/logGroomerConfigType", "description": "Configuration for log groomer sidecar" @@ -2744,6 +3049,30 @@ ], "additionalProperties": false } + }, + "securityContexts": { + "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the wait for migrations.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -2924,7 +3253,7 @@ } }, "securityContext": { - "description": "Security context for the create user job pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the create user job pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -2936,6 +3265,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the create user job. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the create user job.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the create user job.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "resources": { "description": "Resources for the create user job pod", "type": "object", @@ -3150,7 +3517,7 @@ } }, "securityContext": { - "description": "Security context for the migrate database job pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the migrate database job pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -3162,6 +3529,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the migrate database job. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the migrate database job.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the migrate database job.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "useHelmHooks": { "description": "Specify if you want to use the default Helm Hook annotations", "type": "boolean", @@ -3404,12 +3809,12 @@ "additionalProperties": false, "properties": { "ingress": { - "description": "Webserver NetworkPolicy ingress configuration", + "description": "Webserver NetworkPolicyingress configuration", "type": "object", "additionalProperties": false, "properties": { "from": { - "description": "Peers for webserver NetworkPolicy ingress.", + "description": "Peers for webserver NetworkPolicyingress.", "type": "array", "default": [], "items": { @@ -3417,7 +3822,7 @@ } }, "ports": { - "description": "Ports for webserver NetworkPolicy ingress (if `from` is set).", + "description": "Ports for webserver NetworkPolicyingress (if `from` is set).", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.networking.v1.NetworkPolicyPort" @@ -3438,7 +3843,7 @@ } }, "securityContext": { - "description": "Security context for the webserver job pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the webserver job pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -3450,6 +3855,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the webserver. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the webserver.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the webserver.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "resources": { "description": "Resources for webserver pods.", "type": "object", @@ -3753,6 +4196,30 @@ ], "additionalProperties": false } + }, + "securityContexts": { + "description": "Security context definition for the wait for migrations. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the wait for migrations.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } }, @@ -3835,17 +4302,17 @@ "default": [] }, "networkPolicy": { - "description": "Flower NetworkPolicy configuration", + "description": "Flower NetworkPolicyconfiguration", "type": "object", "additionalProperties": false, "properties": { "ingress": { - "description": "Flower NetworkPolicy ingress configuration", + "description": "Flower NetworkPolicyingress configuration", "type": "object", "additionalProperties": false, "properties": { "from": { - "description": "Peers for flower NetworkPolicy ingress.", + "description": "Peers for flower NetworkPolicyingress.", "type": "array", "default": [], "items": { @@ -3853,7 +4320,7 @@ } }, "ports": { - "description": "Ports for flower NetworkPolicy ingress (if `from` is set).", + "description": "Ports for flower NetworkPolicyingress (if `from` is set).", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.networking.v1.NetworkPolicyPort" @@ -4111,7 +4578,7 @@ } }, "securityContext": { - "description": "Security context for the flower pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the flower pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -4123,6 +4590,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the network policy. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the network policy.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the network policy.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "env": { "description": "Add additional env vars to flower.", "type": "array", @@ -4291,7 +4796,7 @@ "default": [] }, "securityContext": { - "description": "Security context for the StatsD pod. If not set, `statsd.uid` will be used.", + "description": "Security context for the StatsD pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -4303,6 +4808,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the statsd. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the statsd.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the statsd.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "podAnnotations": { "description": "Annotations to add to the StatsD pods.", "type": "object", @@ -4488,6 +5031,30 @@ ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" }, + "securityContexts": { + "description": "Security context definition for the PgBouncer. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the PgBouncer.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "service": { "description": "PgBouncer Service configuration.", "type": "object", @@ -4723,6 +5290,30 @@ ], "default": "disable" }, + "securityContexts": { + "description": "Security context definition for the metrics exporter sidecar. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the metrics exporter sidecar.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "livenessProbe": { "description": "LivenessProbe configurations for ``metricsExporterSidecar``", "type": "object", @@ -4919,18 +5510,56 @@ } }, "securityContext": { - "description": "Security context for the cleanup job pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the cleanup job pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, "examples": [ { - "runAsUser": 999, + "runAsUser": 50000, "runAsGroup": 0, "fsGroup": 0 } ] }, + "securityContexts": { + "description": "Security context definition for the redis. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the redis.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 999, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the redis.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "uid": { "description": "Redis run as user parameter.", "type": "integer", @@ -5283,7 +5912,7 @@ } }, "securityContext": { - "description": "Security context for the cleanup job pod. If not set, the values from `securityContext` will be used.", + "description": "Security context for the cleanup job pod (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", "default": {}, @@ -5295,6 +5924,44 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the cleanup. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "pod": { + "description": "Pod security context definition for the cleanup.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "runAsUser": 50000, + "runAsGroup": 0, + "fsGroup": 0 + } + ] + }, + "container": { + "description": "Container security context definition for the cleanup.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "env": { "description": "Add additional env vars to cleanup.", "type": "array", @@ -5547,7 +6214,7 @@ "default": "git-sync" }, "securityContext": { - "description": "Security context for the gitSync container. If not set, the values from `securityContext` will be used.", + "description": "Security context for the `gitSync` container (deprecated, use `securityContexts` instead). If not set, the values from `securityContext` will be used.", "type": "object", "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", "default": {}, @@ -5558,6 +6225,30 @@ } ] }, + "securityContexts": { + "description": "Security context definition for the git sync sidecar. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the git sync sidecar.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } + }, "uid": { "description": "Git sync container run as user parameter.", "type": "integer", @@ -8480,6 +9171,30 @@ } ], "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "securityContexts": { + "description": "Security context definition for the log groomer sidecar. If not set, the values from global `securityContexts` will be used.", + "type": "object", + "x-docsSection": "Kubernetes", + "properties": { + "container": { + "description": "Container security context definition for the log groomer sidecar.", + "type": "object", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext", + "default": {}, + "x-docsSection": "Kubernetes", + "examples": [ + { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + } + } + ] + } + } } } } diff --git a/chart/values.yaml b/chart/values.yaml index 1bbcb9fc7d476..b574175c6486b 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -35,12 +35,17 @@ revisionHistoryLimit: ~ uid: 50000 gid: 0 -# Default security context for airflow +# Default security context for airflow (deprecated, use `securityContexts` instead) securityContext: {} # runAsUser: 50000 # fsGroup: 0 # runAsGroup: 0 +# Detailed default security context for airflow deployments +securityContexts: + pod: {} + containers: {} + # Airflow home directory # Used for mount paths airflowHome: /opt/airflow @@ -491,6 +496,11 @@ workers: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for worker deployments for container and pod level + securityContexts: + pod: {} + container: {} + # Create ServiceAccount serviceAccount: # Specifies whether a ServiceAccount should be created @@ -545,6 +555,9 @@ workers: fixPermissions: false # Annotations to add to worker volumes annotations: {} + # Detailed default security context for persistence for container level + securityContexts: + container: {} kerberosSidecar: # Enable kerberos sidecar @@ -556,6 +569,9 @@ workers: # requests: # cpu: 100m # memory: 128Mi + # Detailed default security context for kerberosSidecar for container level + securityContexts: + container: {} resources: {} # limits: @@ -644,11 +660,17 @@ workers: # requests: # cpu: 100m # memory: 128Mi + # Detailed default security context for logGroomerSidecar for container level + securityContexts: + container: {} waitForMigrations: # Whether to create init container to wait for db migrations enabled: true env: [] + # Detailed default security context for waitForMigrations for container level + securityContexts: + container: {} env: [] @@ -690,11 +712,17 @@ scheduler: strategy: ~ # When not set, the values defined in the global securityContext will be used + # (deprecated, use `securityContexts` instead) securityContext: {} # runAsUser: 50000 # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for scheduler deployments for container and pod level + securityContexts: + pod: {} + container: {} + # Create ServiceAccount serviceAccount: # Specifies whether a ServiceAccount should be created @@ -789,11 +817,17 @@ scheduler: # requests: # cpu: 100m # memory: 128Mi + # Detailed default security context for logGroomerSidecar for container level + securityContexts: + container: {} waitForMigrations: # Whether to create init container to wait for db migrations enabled: true env: [] + # Detailed default security context for waitForMigrations for container level + securityContexts: + container: {} env: [] @@ -839,6 +873,11 @@ createUserJob: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for createUserJob for container and pod level + securityContexts: + pod: {} + container: {} + # Create ServiceAccount serviceAccount: # Specifies whether a ServiceAccount should be created @@ -903,6 +942,11 @@ migrateDatabaseJob: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for migrateDatabaseJob for container and pod level + securityContexts: + pod: {} + container: {} + # Create ServiceAccount serviceAccount: # Specifies whether a ServiceAccount should be created @@ -1009,11 +1053,17 @@ webserver: strategy: ~ # When not set, the values defined in the global securityContext will be used + # (deprecated, use `securityContexts` instead) securityContext: {} # runAsUser: 50000 # fsGroup: 0 # runAsGroup: 0 + # Detailed default security contexts for webserver deployments for container and pod level + securityContexts: + pod: {} + container: {} + # Additional network policies as needed (Deprecated - renamed to `webserver.networkPolicy.ingress.from`) extraNetworkPolicies: [] networkPolicy: @@ -1135,6 +1185,9 @@ webserver: # Whether to create init container to wait for db migrations enabled: true env: [] + # Detailed default security context for waitForMigrations for container level + securityContexts: + container: {} env: [] @@ -1185,6 +1238,10 @@ triggerer: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for triggerer for container and pod level + securityContexts: + pod: {} + container: {} persistence: # Enable persistent volumes enabled: true @@ -1264,11 +1321,17 @@ triggerer: # requests: # cpu: 100m # memory: 128Mi + # Detailed default security context for logGroomerSidecar for container level + securityContexts: + container: {} waitForMigrations: # Whether to create init container to wait for db migrations enabled: true env: [] + # Detailed default security context for waitForMigrations for container level + securityContexts: + container: {} env: [] @@ -1317,6 +1380,11 @@ dagProcessor: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for dagProcessor for container and pod level + securityContexts: + pod: {} + container: {} + resources: {} # limits: # cpu: 100m @@ -1430,6 +1498,11 @@ flower: # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for flower for container and pod level + securityContexts: + pod: {} + container: {} + # Create ServiceAccount serviceAccount: # Specifies whether a ServiceAccount should be created @@ -1514,11 +1587,19 @@ statsd: uid: 65534 # When not set, `statsd.uid` will be used + + # When not set, the values defined in the global securityContext will be used + # (deprecated, use `securityContexts` instead) securityContext: {} # runAsUser: 65534 # fsGroup: 0 # runAsGroup: 0 + # Detailed default security context for statsd deployments for container and pod level + securityContexts: + pod: {} + container: {} + # Additional network policies as needed extraNetworkPolicies: [] resources: {} @@ -1671,6 +1752,10 @@ pgbouncer: uid: 65534 + # Detailed default security context for pgbouncer for container level + securityContexts: + container: {} + metricsExporterSidecar: resources: {} # limits: @@ -1681,6 +1766,10 @@ pgbouncer: # memory: 128Mi sslmode: "disable" + # Detailed default security context for metricsExporterSidecar for container level + securityContexts: + container: {} + livenessProbe: initialDelaySeconds: 10 periodSeconds: 10 @@ -1750,6 +1839,11 @@ redis: # runAsUser: 999 # runAsGroup: 0 + # Detailed default security context for redis for container and pod level + securityContexts: + pod: {} + container: {} + podAnnotations: {} # Auth secret for a private registry # This is used if pulling airflow images from a private registry @@ -1846,6 +1940,10 @@ cleanup: # runAsGroup: 0 env: [] + # Detailed default security context for cleanup for container level + securityContexts: + container: {} + # Specify history limit # When set, overwrite the default k8s number of successful and failed CronJob executions that are saved. failedJobsHistoryLimit: ~ @@ -2048,6 +2146,9 @@ dags: # runAsUser: 65533 # runAsGroup: 0 + securityContexts: + container: {} + extraVolumeMounts: [] env: [] # Supported env vars for gitsync can be found at https://github.com/kubernetes/git-sync diff --git a/docs/helm-chart/production-guide.rst b/docs/helm-chart/production-guide.rst index 65f87f8cf880e..19a4d43689812 100644 --- a/docs/helm-chart/production-guide.rst +++ b/docs/helm-chart/production-guide.rst @@ -331,34 +331,40 @@ In the Airflow Helm chart, the ``securityContext`` can be configured in several * :ref:`uid ` (configures the global uid or RunAsUser) * :ref:`gid ` (configures the global gid or fsGroup) - * :ref:`securityContext ` (same as ``uid`` but allows for setting all `Pod securityContext options `_) + * :ref:`securityContexts ` (same as ``uid`` but allows for setting all `Pod securityContext options `_ and `Container securityContext options `_) -The same way one can configure the global :ref:`securityContext `, it is also possible to configure different values for specific workloads by setting their local ``securityContext`` as follows: +The same way one can configure the global :ref:`securityContexts `, it is also possible to configure different values for specific workloads by setting their local ``securityContexts`` as follows: .. code-block:: yaml workers: - securityContext: - runAsUser: 5000 - fsGroup: 0 + securityContexts: + pod: + runAsUser: 5000 + fsGroup: 0 + containers: + allowPrivilegeEscalation: false + -In the example above, the workers Pod ``securityContext`` will be set to ``runAsUser: 5000`` and ``runAsGroup: 0``. +In the example above, the workers Pod ``securityContexts`` will be set to ``runAsUser: 5000`` and ``fsGroup: 0``. The containers pod will be set to ``allowPrivilegeEscalation: false``. -As one can see, the local setting will take precedence over the global setting when defined. The following explains the precedence rule for ``securityContext`` options in this chart: +As one can see, the local setting will take precedence over the global setting when defined. The following explains the precedence rule for ``securityContexts`` options in this chart: .. code-block:: yaml uid: 40000 gid: 0 - securityContext: - runAsUser: 50000 - fsGroup: 0 + securityContexts: + pod: + runAsUser: 50000 + fsGroup: 0 workers: - securityContext: - runAsUser: 1001 - fsGroup: 0 + securityContexts: + pod: + runAsUser: 1001 + fsGroup: 0 This will generate the following worker deployment: @@ -372,21 +378,21 @@ This will generate the following worker deployment: serviceName: airflow-worker template: spec: - securityContext: # As the securityContext was defined in ``workers``, its value will take priority + securityContext: # As the securityContexts was defined in ``workers``, its value will take priority runAsUser: 1001 fsGroup: 0 -If we remove both the ``securityContext`` and ``workers.securityContext`` from the example above, the output will be the following: +If we remove both the ``securityContexts`` and ``workers.securityContexts`` from the example above, the output will be the following: .. code-block:: yaml uid: 40000 gid: 0 - securityContext: {} + securityContexts: {} workers: - securityContext: {} + securityContexts: {} This will generate the following worker deployment: @@ -410,19 +416,20 @@ This will generate the following worker deployment: - name: worker ... -And finally if we set ``securityContext`` but not ``workers.securityContext``: +And finally if we set ``securityContexts`` but not ``workers.securityContexts``: .. code-block:: yaml uid: 40000 gid: 0 - securityContext: - runAsUser: 50000 - fsGroup: 0 + securityContexts: + pod: + runAsUser: 50000 + fsGroup: 0 workers: - securityContext: {} + securityContexts: {} This will generate the following worker deployment: @@ -436,7 +443,7 @@ This will generate the following worker deployment: serviceName: airflow-worker template: spec: - securityContext: # As the securityContext was not defined in ``workers``, the values from securityContext will take priority + securityContext: # As the securityContexts was not defined in ``workers``, the values from securityContexts will take priority runAsUser: 50000 fsGroup: 0 initContainers: diff --git a/tests/charts/airflow_core/test_scheduler.py b/tests/charts/airflow_core/test_scheduler.py index dbf8161f6057c..8d6a321e267de 100644 --- a/tests/charts/airflow_core/test_scheduler.py +++ b/tests/charts/airflow_core/test_scheduler.py @@ -367,6 +367,59 @@ def test_logs_persistence_changes_volume(self, log_persistence_values, expected_ assert {"name": "logs", **expected_volume} in jmespath.search("spec.template.spec.volumes", docs[0]) + def test_scheduler_security_contexts_are_configurable(self): + docs = render_chart( + values={ + "scheduler": { + "securityContexts": { + "pod": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + }, + "container": { + "allowPrivilegeEscalation": False, + "readOnlyRootFilesystem": True, + }, + } + }, + }, + show_only=["templates/scheduler/scheduler-deployment.yaml"], + ) + assert {"allowPrivilegeEscalation": False, "readOnlyRootFilesystem": True} == jmespath.search( + "spec.template.spec.containers[0].securityContext", docs[0] + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + + def test_scheduler_security_context_legacy(self): + docs = render_chart( + values={ + "scheduler": { + "securityContext": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + } + }, + }, + show_only=["templates/scheduler/scheduler-deployment.yaml"], + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + def test_scheduler_resources_are_configurable(self): docs = render_chart( values={ diff --git a/tests/charts/other/test_statsd.py b/tests/charts/other/test_statsd.py index 4358342cd52c4..04b121be46174 100644 --- a/tests/charts/other/test_statsd.py +++ b/tests/charts/other/test_statsd.py @@ -165,6 +165,59 @@ def test_stastd_resources_are_configurable(self): ) assert "300m" == jmespath.search("spec.template.spec.containers[0].resources.requests.cpu", docs[0]) + def test_statsd_security_contexts_are_configurable(self): + docs = render_chart( + values={ + "statsd": { + "securityContexts": { + "pod": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + }, + "container": { + "allowPrivilegeEscalation": False, + "readOnlyRootFilesystem": True, + }, + } + }, + }, + show_only=["templates/statsd/statsd-deployment.yaml"], + ) + assert {"allowPrivilegeEscalation": False, "readOnlyRootFilesystem": True} == jmespath.search( + "spec.template.spec.containers[0].securityContext", docs[0] + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + + def test_statsd_security_context_legacy(self): + docs = render_chart( + values={ + "statsd": { + "securityContext": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + } + }, + }, + show_only=["templates/statsd/statsd-deployment.yaml"], + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + def test_statsd_resources_are_not_added_by_default(self): docs = render_chart( show_only=["templates/statsd/statsd-deployment.yaml"], diff --git a/tests/charts/security/test_security_context.py b/tests/charts/security/test_security_context.py index 4acf679c4a9da..4fa52ea34b03f 100644 --- a/tests/charts/security/test_security_context.py +++ b/tests/charts/security/test_security_context.py @@ -209,3 +209,205 @@ def test_gitsync_sidecar_and_init_container(self): "spec.template.spec.containers[?name=='git-sync'].securityContext.runAsUser | [0]", docs[index], ) + + # Test securityContexts for main containers + def test_main_container_setting(self): + ctx_value = {"allowPrivilegeEscalation": False} + security_context = {"securityContexts": {"container": ctx_value}} + docs = render_chart( + values={ + "scheduler": {**security_context}, + "webserver": {**security_context}, + "workers": {**security_context}, + "flower": {**security_context}, + "statsd": {**security_context}, + "createUserJob": {**security_context}, + "migrateDatabaseJob": {**security_context}, + "triggerer": {**security_context}, + "pgbouncer": {**security_context}, + "redis": {**security_context}, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/statsd/statsd-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/pgbouncer/pgbouncer-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + ], + ) + + for index in range(len(docs)): + assert ctx_value == jmespath.search( + "spec.template.spec.containers[0].securityContext", docs[index] + ) + + # Test securityContexts for log-groomer-sidecar main container + def test_log_groomer_sidecar_container_setting(self): + ctx_value = {"allowPrivilegeEscalation": False} + spec = {"logGroomerSidecar": {"securityContexts": {"container": ctx_value}}} + docs = render_chart( + values={ + "scheduler": {**spec}, + "workers": {**spec}, + }, + show_only=[ + "templates/scheduler/scheduler-deployment.yaml", + "templates/workers/worker-deployment.yaml", + ], + ) + + for index in range(len(docs)): + assert ctx_value == jmespath.search( + "spec.template.spec.containers[1].securityContext", docs[index] + ) + + # Test securityContexts for metrics-explorer main container + def test_metrics_explorer_container_setting(self): + ctx_value = {"allowPrivilegeEscalation": False} + docs = render_chart( + values={ + "pgbouncer": { + "enabled": True, + "metricsExporterSidecar": {"securityContexts": {"container": ctx_value}}, + }, + }, + show_only=["templates/pgbouncer/pgbouncer-deployment.yaml"], + ) + + assert ctx_value == jmespath.search("spec.template.spec.containers[1].securityContext", docs[0]) + + # Test securityContexts for worker-kerberos main container + def test_worker_kerberos_container_setting(self): + ctx_value = {"allowPrivilegeEscalation": False} + docs = render_chart( + values={ + "workers": { + "kerberosSidecar": {"enabled": True, "securityContexts": {"container": ctx_value}} + }, + }, + show_only=["templates/workers/worker-deployment.yaml"], + ) + + assert ctx_value == jmespath.search("spec.template.spec.containers[2].securityContext", docs[0]) + + # Test securityContexts for the wait-for-migrations init containers + def test_wait_for_migrations_init_container_setting(self): + ctx_value = {"allowPrivilegeEscalation": False} + spec = { + "waitForMigrations": { + "enabled": True, + "securityContexts": {"container": ctx_value}, + } + } + docs = render_chart( + values={ + "scheduler": {**spec}, + "webserver": {**spec}, + "triggerer": {**spec}, + "workers": {"waitForMigrations": {"securityContexts": {"container": ctx_value}}}, + }, + show_only=[ + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/workers/worker-deployment.yaml", + ], + ) + + for index in range(len(docs)): + assert ctx_value == jmespath.search( + "spec.template.spec.initContainers[0].securityContext", docs[index] + ) + + # Test securityContexts for volume-permissions init container + def test_volume_permissions_init_container_setting(self): + docs = render_chart( + values={ + "workers": { + "persistence": { + "enabled": True, + "fixPermissions": True, + "securityContexts": {"container": {"allowPrivilegeEscalation": False}}, + } + } + }, + show_only=["templates/workers/worker-deployment.yaml"], + ) + expected_ctx = { + "allowPrivilegeEscalation": False, + } + + assert expected_ctx == jmespath.search( + "spec.template.spec.initContainers[0].securityContext", docs[0] + ) + + # Test securityContexts for main pods + def test_main_pod_setting(self): + ctx_value = {"runAsUser": 7000} + security_context = {"securityContexts": {"pod": ctx_value}} + docs = render_chart( + values={ + "scheduler": {**security_context}, + "webserver": {**security_context}, + "workers": {**security_context}, + "flower": {**security_context}, + "statsd": {**security_context}, + "createUserJob": {**security_context}, + "migrateDatabaseJob": {**security_context}, + "triggerer": {**security_context}, + "pgbouncer": {**security_context}, + "redis": {**security_context}, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/statsd/statsd-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/pgbouncer/pgbouncer-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + ], + ) + + for index in range(len(docs)): + assert ctx_value == jmespath.search("spec.template.spec.securityContext", docs[index]) + + # Test securityContexts for main pods + def test_main_pod_setting_legacy_security(self): + ctx_value = {"runAsUser": 7000} + security_context = {"securityContext": ctx_value} + docs = render_chart( + values={ + "scheduler": {**security_context}, + "webserver": {**security_context}, + "workers": {**security_context}, + "flower": {**security_context}, + "statsd": {**security_context}, + "createUserJob": {**security_context}, + "migrateDatabaseJob": {**security_context}, + "triggerer": {**security_context}, + "redis": {**security_context}, + }, + show_only=[ + "templates/flower/flower-deployment.yaml", + "templates/scheduler/scheduler-deployment.yaml", + "templates/webserver/webserver-deployment.yaml", + "templates/workers/worker-deployment.yaml", + "templates/statsd/statsd-deployment.yaml", + "templates/jobs/create-user-job.yaml", + "templates/jobs/migrate-database-job.yaml", + "templates/triggerer/triggerer-deployment.yaml", + "templates/redis/redis-statefulset.yaml", + ], + ) + + for index in range(len(docs)): + assert ctx_value == jmespath.search("spec.template.spec.securityContext", docs[index]) diff --git a/tests/charts/webserver/test_webserver.py b/tests/charts/webserver/test_webserver.py index 06b0de62d2f39..4a38f34ad9e83 100644 --- a/tests/charts/webserver/test_webserver.py +++ b/tests/charts/webserver/test_webserver.py @@ -510,6 +510,59 @@ def test_webserver_resources_are_configurable(self): "spec.template.spec.initContainers[0].resources.requests.cpu", docs[0] ) + def test_webserver_security_contexts_are_configurable(self): + docs = render_chart( + values={ + "webserver": { + "securityContexts": { + "pod": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + }, + "container": { + "allowPrivilegeEscalation": False, + "readOnlyRootFilesystem": True, + }, + } + }, + }, + show_only=["templates/webserver/webserver-deployment.yaml"], + ) + assert {"allowPrivilegeEscalation": False, "readOnlyRootFilesystem": True} == jmespath.search( + "spec.template.spec.containers[0].securityContext", docs[0] + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + + def test_webserver_security_context_legacy(self): + docs = render_chart( + values={ + "webserver": { + "securityContext": { + "fsGroup": 1000, + "runAsGroup": 1001, + "runAsNonRoot": True, + "runAsUser": 2000, + } + }, + }, + show_only=["templates/webserver/webserver-deployment.yaml"], + ) + + assert { + "runAsUser": 2000, + "runAsGroup": 1001, + "fsGroup": 1000, + "runAsNonRoot": True, + } == jmespath.search("spec.template.spec.securityContext", docs[0]) + def test_webserver_resources_are_not_added_by_default(self): docs = render_chart( show_only=["templates/webserver/webserver-deployment.yaml"],