diff --git a/.github/workflows/k8s-tests.yml b/.github/workflows/k8s-tests.yml index f7e9a49d3c5..d4b9de1faca 100644 --- a/.github/workflows/k8s-tests.yml +++ b/.github/workflows/k8s-tests.yml @@ -109,17 +109,17 @@ jobs: echo "INFO: status:" kubectl get pods echo "INFO: logs:" - kubectl logs --selector=$3 --all-containers=true + kubectl logs --selector=$3 --all-containers=true exit 1 fi return ${?} } echo "Waiting for init job..." - to_complete "condition=Complete" job "defectdojo.org/component=initializer" + to_complete "condition=Complete" job "defectdojo.org/component=initializer" echo "Waiting for celery pods..." - to_complete "condition=ready" pod "defectdojo.org/component=celery" + to_complete "condition=ready" pod "defectdojo.org/component=celery" echo "Waiting for django pod..." - to_complete "condition=ready" pod "defectdojo.org/component=django" + to_complete "condition=ready" pod "defectdojo.org/component=django" echo "Pods up and ready to rumbole" kubectl get pods RETRY=0 @@ -133,15 +133,15 @@ jobs: --max-time 20 \ --head \ --header "Host: $DD_HOSTNAME" \ - http://$DJANGO_IP/login?next=/) + "http://${DJANGO_IP}/login?next=/") echo $OUT - CR=`echo $OUT | egrep "^HTTP" | cut -d' ' -f2` + CR=$(echo $OUT | egrep "^HTTP" | cut -d' ' -f2) echo $CR if [[ $CR -ne 200 ]]; then echo $RETRY if [[ $RETRY -gt 2 ]]; then kubectl get pods - echo `kubectl logs --tail=30 -l defectdojo.org/component=django -c uwsgi` + echo $(kubectl logs --tail=30 -l defectdojo.org/component=django -c uwsgi) echo "ERROR: cannot display login screen; got HTTP code $CR" exit 1 else @@ -166,7 +166,7 @@ jobs: --data-raw "username=admin&password=$ADMIN_PASS" \ --output /dev/null \ --write-out "%{http_code}\n" \ - http://$DJANGO_IP/api/v2/api-token-auth/) + "http://${DJANGO_IP}/api/v2/api-token-auth/") echo $CR if [[ $CR -ne 200 ]]; then echo "ERROR: login is not possible; got HTTP code $CR" @@ -175,8 +175,8 @@ jobs: echo "Result received" fi echo "Final Check of components" - errors=`kubectl get pods | grep Error | awk '{print $1}'` - if [[ ! -z $errors ]]; then + errors=$(kubectl get pods | grep Error | awk '{print $1}') + if [[ ! -z $errors ]]; then echo "Few pods with errors" for line in $errors; do echo "Dumping log from $line" diff --git a/docs/content/en/open_source/upgrading/2.50.md b/docs/content/en/open_source/upgrading/2.50.md index 289f833a03f..940922ecf81 100644 --- a/docs/content/en/open_source/upgrading/2.50.md +++ b/docs/content/en/open_source/upgrading/2.50.md @@ -2,10 +2,53 @@ title: 'Upgrading to DefectDojo Version 2.50.x' toc_hide: true weight: -20250804 -description: Dropped support for time_zone in System settings. +description: Dropped support for time_zone in System settings and Helm chart changes. --- +## time_zone changes + To simplify the management of the DefectDojo application, it is not necessary to set the time zone in two places (environmental variables and system settings). From now on, environmental variable is supported. Please check that the environmental variable `DD_TIME_ZONE` is set based on your satisfaction. Any [TZ identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is a valid value. Default value is `UTC`. +## Helm Chart Changes + +This release introduces several important changes to the Helm chart configuration: + +### Breaking changes + +#### Volume Management Improvements + +- **Streamlined volume configuration**: The existing volume logic has been removed and replaced with more flexible `extraVolumes` and `extraVolumeMounts` options that provide deployment-agnostic volume management. + +> The previous volume implementation prevented mounting projected volumes (such as secret mounts with renamed key names) and per-container volume mounts (like nginx emptyDir when readOnlyRootFs is enforced). +> The new approach resolves these limitations. + +#### Moved values + +The following Helm chart values have been modified in this release: + +- `redis.transportEncryption.enabled` → `redis.tls.enabled` (aligned with upstream Helm chart) +- `redis.scheme` → `redis.sentinel.enabled` (controls deployment mode and aligns with upstream chart) +- `redis.redisServer` → `redisServer` (prevents potential schema conflicts with upstream chart) +- `redis.transportEncryption.params` → `redisParams` (prevents potential schema conflicts with upstream chart) +- `postgresql.postgresServer` → `postgresServer` (prevents potential schema conflicts with upstream chart) + +### New features + +#### Container and Environment Enhancements + +- **Added extraInitContainers support**: Both Celery and Django deployments now support additional init containers through the `extraInitContainers` configuration option. +- **Enhanced probe configuration for Celery**: Added support for customizing liveness, readiness, and startup probes in both Celery beat and worker deployments. +- **Enhanced environment variable management**: All deployments now include `extraEnv` support for adding custom environment variables. For backwards compatibility, `.Values.extraEnv` can be used to inject common environment variables to all workloads. + +### Other changes + +- **Celery pod annotations**: Now we can add annotations to Celery beat/worker pods separately. +- **Flexible secret deployment**: Added the capability to deploy secrets as regular (non-hooked) resources to address compatibility issues encountered with CI/CD tools (such as ArgoCD). +- **Optional secret references**: Some secret references are now optional, allowing the chart to function even when certain secrets are not created. +- **Fixed secret mounting**: Resolved issues with optional secret mounts and references. +- **Improved code organization**: Minor Helm chart refactoring to enhance readability and maintainability. + +--- + There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 62ac0a762fa..c1c3d4620b8 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 16.7.0 + repository: oci://registry-1.docker.io/bitnamicharts + version: 16.7.15 - name: redis - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 19.6.4 -digest: sha256:20147b5ef71e728a24b1ce410bfbc64885bb824bac17d75dc3ad49e9af5f1b01 -generated: "2025-05-08T15:21:14.221601771Z" +digest: sha256:b7190cec386cfc905413b0e7638bcafac0f6c19f1b0dc0b1bd768c09cf8dc295 +generated: "2025-07-02T07:45:06.165441283+02:00" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 0268c70462f..1f6a60501e1 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 appVersion: "2.50.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.205-dev +version: 1.7.0-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap @@ -11,9 +11,9 @@ maintainers: dependencies: - name: postgresql version: ~16.7.0 - repository: "https://charts.bitnami.com/bitnami" + repository: oci://registry-1.docker.io/bitnamicharts condition: postgresql.enabled - name: redis version: ~19.6.0 - repository: "https://charts.bitnami.com/bitnami" + repository: oci://registry-1.docker.io/bitnamicharts condition: redis.enabled diff --git a/helm/defectdojo/templates/_helpers.tpl b/helm/defectdojo/templates/_helpers.tpl index 311088de423..025b35078db 100644 --- a/helm/defectdojo/templates/_helpers.tpl +++ b/helm/defectdojo/templates/_helpers.tpl @@ -53,15 +53,16 @@ Create the name of the service account to use {{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}} {{- end -}} {{- else -}} -{{- printf "%s" ( .Values.postgresql.postgresServer | default "127.0.0.1" ) -}} +{{- .Values.postgresServer | default "127.0.0.1" | quote -}} {{- end -}} {{- end -}} + {{- define "redis.hostname" -}} {{- if eq .Values.celery.broker "redis" -}} {{- if .Values.redis.enabled -}} {{- printf "%s-%s" .Release.Name "redis-master" | trunc 63 | trimSuffix "-" -}} {{- else -}} -{{- printf "%s" (.Values.celery.brokerHost | default .Values.redis.redisServer) -}} +{{- .Values.redisServer | default "127.0.0.1" | quote -}} {{- end -}} {{- end -}} {{- end -}} @@ -71,9 +72,9 @@ Create the name of the service account to use */}} {{- define "redis.scheme" -}} {{- if eq .Values.celery.broker "redis" -}} -{{- if .Values.redis.transportEncryption.enabled -}} +{{- if .Values.redis.tls.enabled -}} {{- printf "rediss" -}} -{{- else if eq .Values.redis.scheme "sentinel" -}} +{{- else if .Values.redis.sentinel.enabled -}} {{- printf "sentinel" -}} {{- else -}} {{- printf "redis" -}} diff --git a/helm/defectdojo/templates/celery-beat-deployment.yaml b/helm/defectdojo/templates/celery-beat-deployment.yaml index fc96dc10c6c..166f6c2afeb 100644 --- a/helm/defectdojo/templates/celery-beat-deployment.yaml +++ b/helm/defectdojo/templates/celery-beat-deployment.yaml @@ -11,18 +11,16 @@ metadata: app.kubernetes.io/managed-by: {{ .Release.Service }} helm.sh/chart: {{ include "defectdojo.chart" . }} {{- with .Values.extraLabels }} - {{- toYaml . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} -{{- if .Values.celery.annotations }} + {{- with mergeOverwrite .Values.celery.annotations .Values.celery.beat.annotations }} annotations: -{{- with .Values.celery.annotations }} - {{- toYaml . | nindent 4 }} -{{- end }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.celery.beat.replicas }} - {{- if .Values.revisionHistoryLimit }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- with .Values.revisionHistoryLimit }} + revisionHistoryLimit: {{ . }} {{- end }} selector: matchLabels: @@ -44,7 +42,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} annotations: - {{- with .Values.celery.beat.annotations }} + {{- with mergeOverwrite .Values.celery.annotations .Values.celery.beat.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} {{- if eq (.Values.trackConfig | default "disabled") "enabled" }} @@ -54,9 +52,9 @@ spec: {{- end }} spec: serviceAccountName: {{ include "defectdojo.serviceAccountName" . }} - {{- if .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - - name: {{ .Values.imagePullSecrets }} + - name: {{ . }} {{- end }} volumes: - name: run @@ -71,22 +69,16 @@ spec: configMap: name: {{ .Values.django.uwsgi.certificates.configName }} {{- end }} - {{- range .Values.celery.extraVolumes }} - - name: userconfig-{{ .name }} - {{ .type }}: - {{- if (eq .type "configMap") }} - name: {{ .name }} - {{- else if (eq .type "secret") }} - secretName: {{ .name }} - {{- else if (eq .type "hostPath") }} - type: {{ .pathType | default "Directory" }} - path: {{ .hostPath }} - {{- end }} + {{- with .Values.celery.beat.extraVolumes }} + {{- . | toYaml | nindent 6 }} {{- end }} - {{- if or .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled }} + {{- if coalesce .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled .Values.celery.beat.extraInitContainers }} initContainers: + {{- range .Values.celery.beat.extraInitContainers }} + - {{- . | toYaml | nindent 8 }} + {{- end }} {{- end }} - {{- if .Values.cloudsql.enabled }} + {{- if .Values.cloudsql.enabled }} - name: cloudsql-proxy image: {{ .Values.cloudsql.image.repository }}:{{ .Values.cloudsql.image.tag }} imagePullPolicy: {{ .Values.cloudsql.image.pullPolicy }} @@ -115,6 +107,15 @@ spec: name: celery image: "{{ template "celery.repository" . }}:{{ .Values.tag }}" imagePullPolicy: {{ .Values.imagePullPolicy }} + {{- with .Values.celery.beat.livenessProbe }} + livenessProbe: {{ toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.celery.beat.readinessProbe }} + readinessProbe: {{ toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.celery.beat.startupProbe }} + startupProbe: {{ toYaml . | nindent 10 }} + {{- end }} {{- if .Values.securityContext.enabled }} securityContext: {{- toYaml .Values.securityContext.djangoSecurityContext | nindent 10 }} @@ -128,15 +129,12 @@ spec: mountPath: /app/dojo/settings/local_settings.py subPath: file {{- end }} - {{- if .Values.django.uwsgi.certificates.enabled }} + {{- if .Values.django.uwsgi.certificates.enabled }} - name: cert-mount mountPath: {{ .Values.django.uwsgi.certificates.certMountPath }} {{- end }} - {{- range .Values.celery.extraVolumes }} - - name: userconfig-{{ .name }} - readOnly: true - mountPath: {{ .path }} - subPath: {{ .subPath }} + {{- with .Values.celery.beat.extraVolumeMounts }} + {{- . | toYaml | nindent 8 }} {{- end }} envFrom: - configMapRef: @@ -162,8 +160,12 @@ spec: secretKeyRef: name: {{ $fullName }} key: DD_SECRET_KEY + optional: true {{- with .Values.extraEnv }} - {{- toYaml . | nindent 8 }} + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.celery.beat.extraEnv }} + {{- . | toYaml | nindent 8 }} {{- end }} resources: {{- toYaml .Values.celery.beat.resources | nindent 10 }} diff --git a/helm/defectdojo/templates/celery-worker-deployment.yaml b/helm/defectdojo/templates/celery-worker-deployment.yaml index 5fe9b562888..ce4881094e9 100644 --- a/helm/defectdojo/templates/celery-worker-deployment.yaml +++ b/helm/defectdojo/templates/celery-worker-deployment.yaml @@ -13,16 +13,14 @@ metadata: {{- with .Values.extraLabels }} {{- toYaml . | nindent 4 }} {{- end }} -{{- if .Values.celery.annotations }} + {{- with mergeOverwrite .Values.celery.annotations .Values.celery.worker.annotations }} annotations: -{{- with .Values.celery.annotations }} - {{- toYaml . | nindent 4 }} -{{- end }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.celery.worker.replicas }} - {{- if .Values.revisionHistoryLimit }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- with .Values.revisionHistoryLimit }} + revisionHistoryLimit: {{ . }} {{- end }} selector: matchLabels: @@ -44,7 +42,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} annotations: - {{- with .Values.celery.worker.annotations }} + {{- with mergeOverwrite .Values.celery.annotations .Values.celery.worker.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} {{- if eq (.Values.trackConfig | default "disabled") "enabled" }} @@ -54,9 +52,9 @@ spec: {{- end }} spec: serviceAccountName: {{ include "defectdojo.serviceAccountName" . }} - {{- if .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - - name: {{ .Values.imagePullSecrets }} + - name: {{ . }} {{- end }} volumes: {{- if .Values.localsettingspy }} @@ -69,20 +67,14 @@ spec: configMap: name: {{ .Values.django.uwsgi.certificates.configName }} {{- end }} - {{- range .Values.celery.extraVolumes }} - - name: userconfig-{{ .name }} - {{ .type }}: - {{- if (eq .type "configMap") }} - name: {{ .name }} - {{- else if (eq .type "secret") }} - secretName: {{ .name }} - {{- else if (eq .type "hostPath") }} - type: {{ .pathType | default "Directory" }} - path: {{ .hostPath }} - {{- end }} + {{- with .Values.celery.worker.extraVolumes }} + {{- . | toYaml | nindent 6 }} {{- end }} - {{- if or .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled }} + {{- if coalesce .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled .Values.celery.worker.extraInitContainers }} initContainers: + {{- range .Values.celery.worker.extraInitContainers }} + - {{- . | toYaml | nindent 8 }} + {{- end }} {{- end }} {{- if .Values.cloudsql.enabled }} - name: cloudsql-proxy @@ -111,13 +103,22 @@ spec: - name: celery image: "{{ template "celery.repository" . }}:{{ .Values.tag }}" imagePullPolicy: {{ .Values.imagePullPolicy }} + {{- with .Values.celery.worker.livenessProbe }} + livenessProbe: {{ toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.celery.worker.readinessProbe }} + readinessProbe: {{ toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.celery.worker.startupProbe }} + startupProbe: {{ toYaml . | nindent 10 }} + {{- end }} {{- if .Values.securityContext.enabled }} securityContext: {{- toYaml .Values.securityContext.djangoSecurityContext | nindent 10 }} {{- end }} command: ['/entrypoint-celery-worker.sh'] volumeMounts: - {{- if .Values.localsettingspy }} + {{- if .Values.localsettingspy }} - name: localsettingspy readOnly: true mountPath: /app/dojo/settings/local_settings.py @@ -127,11 +128,8 @@ spec: - name: cert-mount mountPath: {{ .Values.django.uwsgi.certificates.certMountPath }} {{- end }} - {{- range .Values.celery.extraVolumes }} - - name: userconfig-{{ .name }} - readOnly: true - mountPath: {{ .path }} - subPath: {{ .subPath }} + {{- with .Values.celery.worker.extraVolumeMounts }} + {{- . | toYaml | nindent 8 }} {{- end }} envFrom: - configMapRef: @@ -157,8 +155,12 @@ spec: secretKeyRef: name: {{ $fullName }} key: DD_SECRET_KEY + optional: true {{- with .Values.extraEnv }} - {{- toYaml . | nindent 8 }} + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.celery.worker.extraEnv }} + {{- . | toYaml | nindent 8 }} {{- end }} resources: {{- toYaml .Values.celery.worker.resources | nindent 10 }} diff --git a/helm/defectdojo/templates/configmap.yaml b/helm/defectdojo/templates/configmap.yaml index 74d516981c7..e89279e3eea 100644 --- a/helm/defectdojo/templates/configmap.yaml +++ b/helm/defectdojo/templates/configmap.yaml @@ -1,4 +1,5 @@ {{- $fullName := include "defectdojo.fullname" . -}} +{{- $defaultBrokerParams := ternary "ssl_cert_reqs=optional" "" .Values.redis.tls.enabled -}} apiVersion: v1 kind: ConfigMap metadata: @@ -28,7 +29,7 @@ data: DD_CELERY_BROKER_USER: '' DD_CELERY_BROKER_HOST: {{ if eq .Values.celery.broker "redis" }}{{ template "redis.hostname" . }}{{ end }} DD_CELERY_BROKER_PORT: '{{ if eq .Values.celery.broker "redis" }}{{- if ( hasKey .Values.redis "master" ) -}}{{ .Values.redis.master.service.ports.redis }}{{ else }}6379{{ end }}{{- end -}}' - DD_CELERY_BROKER_PARAMS: '{{ if eq .Values.celery.broker "redis" }}{{- if .Values.redis.transportEncryption.enabled -}}{{ .Values.redis.transportEncryption.params | default "ssl_cert_reqs=optional" }}{{ end }}{{ end }}' + DD_CELERY_BROKER_PARAMS: '{{ .Values.redisParams | default $defaultBrokerParams }}' DD_CELERY_BROKER_PATH: '{{ .Values.celery.path | default "//" }}' DD_CELERY_LOG_LEVEL: {{ .Values.celery.logLevel }} DD_CELERY_WORKER_POOL_TYPE: {{ .Values.celery.worker.appSettings.poolType | default "solo" }} @@ -54,5 +55,6 @@ data: {{- if .Values.django.uwsgi.certificates.enabled }} REQUESTS_CA_BUNDLE: {{ .Values.django.uwsgi.certificates.certMountPath }}{{ .Values.django.uwsgi.certificates.certFileName }} {{- end }} -{{- with .Values.extraConfigs }} - {{- toYaml . | nindent 2 }}{{- end }} +{{- with .Values.extraConfigs }} + {{- toYaml . | nindent 2 }} +{{- end }} diff --git a/helm/defectdojo/templates/django-deployment.yaml b/helm/defectdojo/templates/django-deployment.yaml index 0f6d5fc0076..fb77e8f7e88 100644 --- a/helm/defectdojo/templates/django-deployment.yaml +++ b/helm/defectdojo/templates/django-deployment.yaml @@ -12,20 +12,18 @@ metadata: {{- with .Values.extraLabels }} {{- toYaml . | nindent 4 }} {{- end }} -{{- if .Values.django.annotations }} + {{- with .Values.django.annotations }} annotations: -{{- with .Values.django.annotations }} - {{- toYaml . | nindent 4 }} -{{- end }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.django.replicas }} {{- with .Values.django.strategy }} strategy: {{- toYaml . | nindent 4 }} {{- end }} - {{- if .Values.revisionHistoryLimit }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- with .Values.revisionHistoryLimit }} + revisionHistoryLimit: {{ . }} {{- end }} selector: matchLabels: @@ -61,9 +59,9 @@ spec: {{- end }} spec: serviceAccountName: {{ include "defectdojo.serviceAccountName" . }} - {{- if .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - - name: {{ .Values.imagePullSecrets }} + - name: {{ quote . }} {{- end }} {{- if .Values.django.mediaPersistentVolume.enabled }} securityContext: @@ -72,41 +70,34 @@ spec: volumes: - name: run emptyDir: {} - {{- if .Values.localsettingspy }} + {{- if .Values.localsettingspy }} - name: localsettingspy configMap: name: {{ $fullName }}-localsettingspy {{- end }} - {{- if .Values.django.uwsgi.certificates.enabled }} + {{- if .Values.django.uwsgi.certificates.enabled }} - name: cert-mount configMap: name: {{ .Values.django.uwsgi.certificates.configName }} {{- end }} - {{- range .Values.django.extraVolumes }} - - name: userconfig-{{ .name }} - {{ .type }}: - {{- if (eq .type "configMap") }} - name: {{ .name }} - {{- else if (eq .type "secret") }} - secretName: {{ .name }} - {{- else if (eq .type "hostPath") }} - type: {{ .pathType | default "Directory" }} - path: {{ .hostPath }} - {{- end }} + {{- with .Values.django.extraVolumes }} + {{- . | toYaml | nindent 6 }} {{- end }} {{- if .Values.django.mediaPersistentVolume.enabled }} - name: {{ .Values.django.mediaPersistentVolume.name }} - {{- if eq .Values.django.mediaPersistentVolume.type "pvc" }} + {{- if eq .Values.django.mediaPersistentVolume.type "pvc" }} persistentVolumeClaim: claimName: {{ include "django.pvc_name" $ }} {{ else }} emptyDir: {} {{- end }} {{- end }} - {{- if or .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled }} + {{- if coalesce .Values.dbMigrationChecker.enabled .Values.cloudsql.enabled .Values.django.extraInitContainers }} initContainers: + {{- range .Values.django.extraInitContainers }} + - {{- . | toYaml | nindent 8 }} {{- end }} - {{- if .Values.cloudsql.enabled }} + {{- if .Values.cloudsql.enabled }} - name: cloudsql-proxy image: {{ .Values.cloudsql.image.repository }}:{{ .Values.cloudsql.image.tag }} imagePullPolicy: {{ .Values.cloudsql.image.pullPolicy }} @@ -129,6 +120,7 @@ spec: {{- $newContext := merge . (dict "fullName" $fullName) }} {{- include "dbMigrationChecker" $newContext | nindent 6 }} {{- end }} + {{- end }} containers: {{- if and .Values.monitoring.enabled .Values.monitoring.prometheus.enabled }} - name: metrics @@ -157,23 +149,18 @@ spec: volumeMounts: - name: run mountPath: /run/defectdojo - {{- if .Values.localsettingspy }} + {{- if .Values.localsettingspy }} - name: localsettingspy readOnly: true mountPath: /app/dojo/settings/local_settings.py subPath: file {{- end }} - {{- if .Values.django.uwsgi.certificates.enabled }} + {{- if .Values.django.uwsgi.certificates.enabled }} - name: cert-mount mountPath: {{ .Values.django.uwsgi.certificates.certMountPath }} {{- end }} - {{- range .Values.django.extraVolumes }} - {{- if (eq .container "uwsgi") }} - - name: userconfig-{{ .name }} - readOnly: true - mountPath: {{ .path }} - subPath: {{ .subPath }} - {{- end }} + {{- with .Values.django.uwsgi.extraVolumeMounts }} + {{- . | toYaml | nindent 8 }} {{- end }} {{- if .Values.django.mediaPersistentVolume.enabled }} - name: {{ .Values.django.mediaPersistentVolume.name }} @@ -211,17 +198,22 @@ spec: secretKeyRef: name: {{ $fullName }} key: DD_SECRET_KEY + optional: true - name: DD_CREDENTIAL_AES_256_KEY valueFrom: secretKeyRef: name: {{ $fullName }} key: DD_CREDENTIAL_AES_256_KEY + optional: true - name: DD_SESSION_COOKIE_SECURE value: {{- if or .Values.django.ingress.activateTLS .Values.django.nginx.tls.enabled }} "True" {{- else }} "False" {{- end }} - name: DD_CSRF_COOKIE_SECURE value: {{- if or .Values.django.ingress.activateTLS .Values.django.nginx.tls.enabled }} "True" {{- else }} "False" {{- end }} {{- with .Values.extraEnv }} - {{- toYaml . | nindent 8 }} + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.django.uwsgi.extraEnv }} + {{- . | toYaml | nindent 8 }} {{- end }} {{- if .Values.django.uwsgi.livenessProbe.enabled }} livenessProbe: @@ -249,13 +241,8 @@ spec: volumeMounts: - name: run mountPath: /run/defectdojo - {{- range .Values.django.extraVolumes }} - {{- if (eq .container "nginx") }} - - name: userconfig-{{ .name }} - readOnly: true - mountPath: {{ .path }} - subPath: {{ .subPath }} - {{- end }} + {{- with .Values.django.nginx.extraVolumeMounts }} + {{- . | toYaml | nindent 8 }} {{- end }} {{- if .Values.django.mediaPersistentVolume.enabled }} - name: {{ .Values.django.mediaPersistentVolume.name }} @@ -278,6 +265,12 @@ spec: value: '{{ .Values.django.nginx.tls.enabled }}' - name: GENERATE_TLS_CERTIFICATE value: '{{ .Values.django.nginx.tls.generateCertificate }}' + {{- with .Values.extraEnv }} + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.django.nginx.extraEnv }} + {{- . | toYaml | nindent 8 }} + {{- end }} {{- if .Values.django.uwsgi.livenessProbe.enabled }} livenessProbe: httpGet: diff --git a/helm/defectdojo/templates/initializer-job.yaml b/helm/defectdojo/templates/initializer-job.yaml index 223799bf444..668812d1a08 100644 --- a/helm/defectdojo/templates/initializer-job.yaml +++ b/helm/defectdojo/templates/initializer-job.yaml @@ -39,12 +39,12 @@ spec: {{- end }} spec: serviceAccountName: {{ include "defectdojo.serviceAccountName" . }} - {{- if .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - - name: {{ .Values.imagePullSecrets }} + - name: {{ . }} {{- end }} volumes: - {{- if .Values.localsettingspy }} + {{- if .Values.localsettingspy }} - name: localsettingspy configMap: name: {{ $fullName }}-localsettingspy @@ -62,7 +62,7 @@ spec: {{- end }} {{- end }} initContainers: - {{- if .Values.cloudsql.enabled }} + {{- if .Values.cloudsql.enabled }} - name: cloudsql-proxy image: {{ .Values.cloudsql.image.repository }}:{{ .Values.cloudsql.image.tag }} imagePullPolicy: {{ .Values.cloudsql.image.pullPolicy }} @@ -79,6 +79,13 @@ spec: {{- if .Values.cloudsql.use_private_ip }} - "-ip_address_types=PRIVATE" {{- end }} + volumeMounts: + {{- range .Values.initializer.extraVolumes }} + - name: userconfig-{{ .name }} + readOnly: true + mountPath: {{ .path }} + subPath: {{ .subPath }} + {{- end }} {{- end }} - name: wait-for-db command: @@ -95,14 +102,21 @@ spec: - configMapRef: name: {{ $fullName }} - secretRef: - name: {{ $fullName }} + name: {{ $fullName }}-extrasecrets optional: true env: - {{- with .Values.extraEnv }} + {{- with .Values.initializer.extraEnv }} {{- toYaml . | nindent 8 }} {{- end }} resources: {{- toYaml .Values.initializer.resources | nindent 10 }} + volumeMounts: + {{- range .Values.initializer.extraVolumes }} + - name: userconfig-{{ .name }} + readOnly: true + mountPath: {{ .path }} + subPath: {{ .subPath }} + {{- end }} containers: - name: initializer image: "{{ template "initializer.repository" . }}:{{ .Values.tag }}" @@ -112,7 +126,7 @@ spec: {{- toYaml .Values.securityContext.djangoSecurityContext | nindent 10 }} {{- end }} volumeMounts: - {{- if .Values.localsettingspy }} + {{- if .Values.localsettingspy }} - name: localsettingspy readOnly: true mountPath: /app/dojo/settings/local_settings.py @@ -131,13 +145,17 @@ spec: name: {{ $fullName }} - secretRef: name: {{ $fullName }} + optional: true + - secretRef: + name: {{ $fullName }}-extrasecrets + optional: true env: - name: DD_DATABASE_PASSWORD valueFrom: secretKeyRef: name: {{ .Values.postgresql.auth.existingSecret }} key: {{ .Values.postgresql.auth.secretKeys.userPasswordKey }} - {{- with .Values.extraEnv }} + {{- with .Values.initializer.extraEnv }} {{- toYaml . | nindent 8 }} {{- end }} resources: diff --git a/helm/defectdojo/templates/sa.yaml b/helm/defectdojo/templates/sa.yaml index 2c6b166510c..4345da6360a 100644 --- a/helm/defectdojo/templates/sa.yaml +++ b/helm/defectdojo/templates/sa.yaml @@ -15,9 +15,11 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} annotations: + {{- if (not .Values.disableHooks) }} helm.sh/resource-policy: keep helm.sh/hook: "pre-install" helm.sh/hook-delete-policy: "before-hook-creation" + {{- end }} {{- with .Values.annotations }} {{ toYaml . | nindent 4 }} {{- end }} diff --git a/helm/defectdojo/templates/secret-postgresql.yaml b/helm/defectdojo/templates/secret-postgresql.yaml index 979e4d75c9c..12924bb29c5 100644 --- a/helm/defectdojo/templates/secret-postgresql.yaml +++ b/helm/defectdojo/templates/secret-postgresql.yaml @@ -12,9 +12,11 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} annotations: + {{- if (not .Values.disableHooks) }} helm.sh/resource-policy: keep helm.sh/hook: "pre-install" helm.sh/hook-delete-policy: "before-hook-creation" + {{- end }} {{- with .Values.secrets.annotations }} {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/defectdojo/templates/secret-redis.yaml b/helm/defectdojo/templates/secret-redis.yaml index 35abc641fe9..f6d102c2513 100644 --- a/helm/defectdojo/templates/secret-redis.yaml +++ b/helm/defectdojo/templates/secret-redis.yaml @@ -12,9 +12,11 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} annotations: + {{- if (not .Values.disableHooks) }} helm.sh/resource-policy: keep helm.sh/hook: "pre-install" helm.sh/hook-delete-policy: "before-hook-creation" + {{- end }} {{- with .Values.secrets.annotations }} {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/defectdojo/templates/secret.yaml b/helm/defectdojo/templates/secret.yaml index e09dad92244..c3a3c56f6c4 100644 --- a/helm/defectdojo/templates/secret.yaml +++ b/helm/defectdojo/templates/secret.yaml @@ -13,9 +13,11 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} annotations: + {{- if (not .Values.disableHooks) }} helm.sh/resource-policy: keep helm.sh/hook: "pre-install" helm.sh/hook-delete-policy: "before-hook-creation" + {{- end }} {{- with .Values.secrets.annotations }} {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/defectdojo/templates/tests/unit-tests.yaml b/helm/defectdojo/templates/tests/unit-tests.yaml index 252c92090e5..2f390733b22 100644 --- a/helm/defectdojo/templates/tests/unit-tests.yaml +++ b/helm/defectdojo/templates/tests/unit-tests.yaml @@ -12,9 +12,9 @@ metadata: helm.sh/hook: test-success spec: serviceAccountName: {{ include "defectdojo.serviceAccountName" . }} - {{- if .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - - name: {{ .Values.imagePullSecrets }} + - name: {{ . }} {{- end }} containers: - name: unit-tests @@ -51,11 +51,13 @@ spec: secretKeyRef: name: {{ $fullName }} key: DD_SECRET_KEY + optional: true - name: DD_CREDENTIAL_AES_256_KEY valueFrom: secretKeyRef: name: {{ $fullName }} key: DD_CREDENTIAL_AES_256_KEY + optional: true resources: {{- toYaml .Values.tests.unitTests.resources | nindent 8 }} restartPolicy: Never diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 5d073474a08..ec4eecd601d 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -12,7 +12,10 @@ createPostgresqlSecret: false # - enabled, enables tracking configuration changes based on SHA256 # trackConfig: disabled -# extraLabels: {} +# Avoid using pre-install hooks, which might cause issues with ArgoCD +disableHooks: false + +extraLabels: {} # Add extra labels for k8s # Enables application network policy @@ -64,7 +67,7 @@ imagePullPolicy: Always repositoryPrefix: defectdojo # When using a private registry, name of the secret that holds the registry secret (eg deploy token from gitlab-ci project) # Create secrets as: kubectl create secret docker-registry defectdojoregistrykey --docker-username=registry_username --docker-password=registry_password --docker-server='https://index.docker.io/v1/' -# imagePullSecrets: defectdojoregistrykey +imagePullSecrets: ~ tag: latest # Additional labels to add to the pods: @@ -73,7 +76,7 @@ tag: latest podLabels: {} # Allow overriding of revisionHistoryLimit across all deployments. -# revisionHistoryLimit: 10 +revisionHistoryLimit: 10 securityContext: enabled: true @@ -145,14 +148,37 @@ secrets: # Components celery: broker: redis - # To use an external celery broker, set the hostname here - brokerHost: "" logLevel: INFO + # Common annotations to worker and beat deployments and pods. annotations: {} beat: + # Annotations for the Celery beat deployment. annotations: {} affinity: {} + # Additional environment variables injected to Celery beat containers. + extraEnv: [] + # A list of additional initContainers to run before celery beat containers. + extraInitContainers: [] + # Array of additional volume mount points for the celery beat containers. + extraVolumeMounts: [] + # A list of extra volumes to mount + # @type: array + extraVolumes: [] + # Enable liveness probe for Celery beat container. + livenessProbe: {} + # exec: + # command: + # - bash + # - -c + # - celery -A dojo inspect ping -t 5 + # initialDelaySeconds: 30 + # periodSeconds: 60 + # timeoutSeconds: 10 nodeSelector: {} + # Annotations for the Celery beat pods. + podAnnotations: {} + # Enable readiness probe for Celery beat container. + readinessProbe: {} replicas: 1 resources: requests: @@ -161,11 +187,37 @@ celery: limits: cpu: 2000m memory: 256Mi + # Enable startup probe for Celery beat container. + startupProbe: {} tolerations: [] worker: + # Annotations for the Celery worker deployment. annotations: {} affinity: {} + # Additional environment variables injected to Celery worker containers. + extraEnv: [] + # A list of additional initContainers to run before celery worker containers. + extraInitContainers: [] + # Array of additional volume mount points for the celery worker containers. + extraVolumeMounts: [] + # A list of extra volumes to mount. + # @type: array + extraVolumes: [] + # Enable liveness probe for Celery worker containers. + livenessProbe: {} + # exec: + # command: + # - bash + # - -c + # - celery -A dojo inspect ping -t 5 + # initialDelaySeconds: 30 + # periodSeconds: 60 + # timeoutSeconds: 10 nodeSelector: {} + # Annotations for the Celery beat pods. + podAnnotations: {} + # Enable readiness probe for Celery worker container. + readinessProbe: {} replicas: 1 resources: requests: @@ -174,6 +226,8 @@ celery: limits: cpu: 2000m memory: 512Mi + # Enable startup probe for Celery worker container. + startupProbe: {} tolerations: [] appSettings: poolType: solo @@ -185,39 +239,6 @@ celery: # concurrency: 8 # prefetchMultiplier: 128 - # A list of extra volumes to mount. This - # is useful for bringing in extra data that can be referenced by other configurations - # at a well known path, such as local_settings. The - # value of this should be a list of objects. - # - # Example: - # - # ```yaml - # extraVolumes: - # - type: configMap - # name: local_settings - # path: /app/dojo/settings/local_settings.py - # subPath: local_settings.py - # - type: hostPath - # name: host_directory - # path: /tmp - # hostPath: /tmp - # ``` - # - # Each object supports the following keys: - # - # - `type` - Type of the volume, must be one of "configMap", "secret", "hostPath". Case sensitive. - # Even is supported we are highly recommending to avoid hostPath for security reasons (usually blocked by PSP) - # - `name` - Name of the configMap or secret to be mounted. This also controls - # the path that it is mounted to. The volume will be mounted to `/consul/userconfig/`. - # - `path` - defines where file should be exposed - # - `subPath` - extracts only particular file from secret or configMap - # - `pathType` - only for hostPath, can be one of the "DirectoryOrCreate", "Directory" (default), "FileOrCreate", - # "File", "Socket", "CharDevice", "BlockDevice" - # - `hostPath` - only for hostPath, file or directory from local host - # @type: array - extraVolumes: [] - django: annotations: {} service: @@ -236,6 +257,16 @@ django: # nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" # nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" nginx: + # To extra environment variables to the nginx container, you can use extraEnv. For example: + # extraEnv: + # - name: FOO + # valueFrom: + # configMapKeyRef: + # name: foo + # key: bar + extraEnv: [] + # Array of additional volume mount points for nginx containers. + extraVolumeMounts: [] tls: enabled: false generateCertificate: false @@ -251,6 +282,17 @@ django: strategy: {} tolerations: [] uwsgi: + # To add (or override) extra variables which need to be pulled from another configMap, you can + # use extraEnv. For example: + # extraEnv: + # - name: DD_DATABASE_HOST + # valueFrom: + # configMapKeyRef: + # name: my-other-postgres-configmap + # key: cluster_endpoint + extraEnv: [] + # Array of additional volume mount points for uwsgi containers. + extraVolumeMounts: [] livenessProbe: # Enable liveness checks on uwsgi container. enabled: true @@ -289,47 +331,16 @@ django: enableDebug: false # this also requires DD_DEBUG to be set to True certificates: # includes additional CA certificate as volume, it refrences REQUESTS_CA_BUNDLE env varible - # to create configMap `kubectl create cm defectdojo-ca-certs --from-file=ca.crt` + # to create configMap `kubectl create cm defectdojo-ca-certs --from-file=ca.crt` # NOTE: it reflects REQUESTS_CA_BUNDLE for celery workers, beats as well enabled: false configName: defectdojo-ca-certs certMountPath: /certs/ certFileName: ca.crt - # A list of extra volumes to mount. This - # is useful for bringing in extra data that can be referenced by other configurations - # at a well known path, such as local_settings. The - # value of this should be a list of objects. - # - # Example: - # - # ```yaml - # extraVolumes: - # - type: configMap - # name: local_settings - # path: /app/dojo/settings/local_settings.py - # container: uwsgi - # subPath: local_settings.py - # - type: hostPath - # name: host_directory - # path: /app/dojo/settings/ - # hostPath: /var/run - # container: uwsgi - # ``` - # - # Each object supports the following keys: - # - # - `type` - Type of the volume, must be one of "configMap", "secret", "hostPath". Case sensitive. - # Even is supported we are highly recommending to avoid hostPath for security reasons (usually blocked by PSP) - # - `name` - Name of the configMap or secret to be mounted. This also controls - # the path that it is mounted to. The volume will be mounted to `/consul/userconfig/`. - # - `path` - defines where file should be exposed - # - `container` - defines where volume needs to be mounted, must be uwsgi or nginx - # - `subPath` - extracts only particular file from secret or configMap - # - `pathType` - only for hostPath, can be one of the "DirectoryOrCreate", "Directory" (default), "FileOrCreate", - # "File", "Socket", "CharDevice", "BlockDevice" - # - `hostPath` - only for hostPath, file or directory from local host - # @type: array + # A list of additional initContainers to run before the uwsgi and nginx containers. + extraInitContainers: [] + # A list of extra volumes to mount. extraVolumes: [] # This feature needs more preparation before can be enabled, please visit KUBERNETES.md#media-persistent-volume @@ -358,6 +369,7 @@ initializer: keepSeconds: 60 # A positive integer will keep this Job and Pod deployed for the specified number of seconds, after which they will be removed. For all other values, the Job and Pod will remain deployed. affinity: {} nodeSelector: {} + tolerations: [] resources: requests: cpu: 100m @@ -365,38 +377,11 @@ initializer: limits: cpu: 2000m memory: 512Mi - - # A list of extra volumes to mount. This - # is useful for bringing in extra data that can be referenced by other configurations - # at a well known path, such as local_settings. The - # value of this should be a list of objects. - # - # Example: - # - # ```yaml - # extraVolumes: - # - type: configMap - # name: local_settings - # path: /app/dojo/settings/local_settings.py - # subPath: local_settings.py - # - type: hostPath - # name: host_directory - # path: /tmp - # hostPath: /tmp - # ``` - # - # Each object supports the following keys: - # - # - `type` - Type of the volume, must be one of "configMap", "secret", "hostPath". Case sensitive. - # Even is supported we are highly recommending to avoid hostPath for security reasons (usually blocked by PSP) - # - `name` - Name of the configMap or secret to be mounted. This also controls - # the path that it is mounted to. The volume will be mounted to `/consul/userconfig/`. - # - `path` - defines where file should be exposed - # - `subPath` - extracts only particular file from secret or configMap - # - `pathType` - only for hostPath, can be one of the "DirectoryOrCreate", "Directory" (default), "FileOrCreate", - # "File", "Socket", "CharDevice", "BlockDevice" - # - `hostPath` - only for hostPath, file or directory from local host - # @type: array + # Additional environment variables injected to the initializer job pods. + extraEnv: [] + # Array of additional volume mount points for the initializer job (init)containers. + extraVolumeMounts: [] + # A list of extra volumes to attach to the initializer job pods. extraVolumes: [] # staticName defines whether name of the job will be the same (e.g., "defectdojo-initializer") @@ -404,10 +389,9 @@ initializer: # This might be handy for ArgoCD deployments staticName: false +# For more advance options check the bitnami chart documentation: https://github.com/bitnami/charts/tree/main/bitnami/postgresql postgresql: - # To use an external PostgreSQL instance (like CloudSQL), set enabled to false, set items in auth part for authentication, - # and uncomment the line below: - # postgresServer: "127.0.0.1" + # To use an external instance, switch enabled to `false` and set the address in `postgresServer` below enabled: true auth: username: defectdojo @@ -477,26 +461,31 @@ gke: # Only works with serviceAccount.create = true workloadIdentityEmail: "" -# For more advance options check the bitnami chart documentation: https://github.com/bitnami/charts/tree/master/bitnami/redis +# For more advance options check the bitnami chart documentation: https://github.com/bitnami/charts/tree/main/bitnami/redis redis: + # To use an external instance, switch enabled to `false`` and set the address in `redisServer` below enabled: true - scheme: "redis" - transportEncryption: - enabled: false - params: '' auth: existingSecret: defectdojo-redis-specific existingSecretPasswordKey: redis-password password: "" architecture: standalone - # To use an external Redis instance, set enabled to false and uncomment - # the line below: - # redisServer: myrediscluster # To use a different port for Redis (default: 6379) add a port number and uncomment the lines below: # master: # service: # ports: # redis: xxxx + # Sentinel configuration parameters + sentinel: + enabled: false + # If TLS is enabled, the Redis broker will use the redis:// and optionally mount the certificates + # from an existing secret. + tls: + enabled: false + # existingSecret: redis-tls + # certFilename: tls.crt + # certKeyFilename: tls.key + # certCAFilename: ca.crt # To add extra variables not predefined by helm config it is possible to define in extraConfigs block, e.g. below: # NOTE Do not store any kind of sensitive information inside of it @@ -531,3 +520,14 @@ extraConfigs: {} # MIDDLEWARE = [ # 'debug_toolbar.middleware.DebugToolbarMiddleware', # ] + MIDDLEWARE +# +# External database support. +# +# To use an external Redis instance, set `redis.enabled` to false and set the address here: +redisServer: ~ +# Parameters attached to the redis connection string, defaults to "ssl_cert_reqs=optional" if `redis.tls.enabled` +redisParams: "" +# +# To use an external PostgreSQL instance (like CloudSQL), set `postgresql.enabled` to false, +# set items in `postgresql.auth` part for authentication, and set the address here: +postgresServer: ~