diff --git a/.github/workflows/k8s-tests.yml b/.github/workflows/k8s-tests.yml index f9e8cd3802..251820c50e 100644 --- a/.github/workflows/k8s-tests.yml +++ b/.github/workflows/k8s-tests.yml @@ -108,17 +108,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 @@ -132,15 +132,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 @@ -165,7 +165,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" @@ -174,8 +174,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.51.md b/docs/content/en/open_source/upgrading/2.51.md index 587eba9613..fd9cab80d5 100644 --- a/docs/content/en/open_source/upgrading/2.51.md +++ b/docs/content/en/open_source/upgrading/2.51.md @@ -2,6 +2,48 @@ title: 'Upgrading to DefectDojo Version 2.51.x' toc_hide: true weight: -20250902 -description: No special instructions. +description: Helm chart changes. --- -There are no special instructions for upgrading to 2.51.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.51.0) for the contents of the release. + +## 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.51.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.51.0) for the contents of the release. diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index f2617ac471..1e1d4ef8b4 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 appVersion: "2.51.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.206-dev +version: 1.7.0-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap diff --git a/helm/defectdojo/templates/_helpers.tpl b/helm/defectdojo/templates/_helpers.tpl index 311088de42..025b35078d 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 fc96dc10c6..166f6c2afe 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 5fe9b56288..ce4881094e 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 74d516981c..e89279e3ee 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 0f6d5fc007..fb77e8f7e8 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 223799bf44..668812d1a0 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 2c6b166510..4345da6360 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 979e4d75c9..12924bb29c 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 35abc641fe..f6d102c251 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 e09dad9224..c3a3c56f6c 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 252c92090e..2f390733b2 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 5d073474a0..ec4eecd601 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: ~