From d5e3ea865af7922a4f64851381f973ddbee43815 Mon Sep 17 00:00:00 2001 From: jonasschultheiss Date: Tue, 9 Jun 2026 09:10:28 +0200 Subject: [PATCH] feat(helm): add Gateway API HTTPRoute and External Secrets Operator support Add HTTPRoute template as an alternative to the classic Ingress resource for users running Kubernetes Gateway API controllers. The template supports parentRefs, hostnames, flexible match rules with filters, and automatically selects port 80/443 based on the existing nginx TLS configuration. Add ExternalSecret template for integrating with the External Secrets Operator (ESO), allowing users to sync secrets from external stores (e.g. HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) instead of managing them directly in Helm values or Kubernetes Secrets. Both features are disabled by default and fully opt-in. --- .../templates/django-httproute.yaml | 55 +++++++++++++++++++ .../defectdojo/templates/external-secret.yaml | 37 +++++++++++++ helm/defectdojo/values.yaml | 37 +++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 helm/defectdojo/templates/django-httproute.yaml create mode 100644 helm/defectdojo/templates/external-secret.yaml diff --git a/helm/defectdojo/templates/django-httproute.yaml b/helm/defectdojo/templates/django-httproute.yaml new file mode 100644 index 00000000000..c04106ce7ff --- /dev/null +++ b/helm/defectdojo/templates/django-httproute.yaml @@ -0,0 +1,55 @@ +{{- if .Values.django.httpRoute.enabled -}} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} + labels: + defectdojo.org/component: django + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- with .Values.django.httpRoute.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.extraAnnotations .Values.django.httpRoute.annotations }} + annotations: + {{- range $key, $value := .Values.extraAnnotations }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- with .Values.django.httpRoute.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + {{- with .Values.django.httpRoute.parentRefs }} + parentRefs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.django.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range .Values.django.httpRoute.rules }} + {{- with .matches }} + - matches: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .filters }} + filters: + {{- toYaml . | nindent 8 }} + {{- end }} + backendRefs: + - group: "" + kind: Service + name: {{ $fullName }}-django + port: {{ $.Values.django.nginx.tls.enabled | ternary 443 80 }} + weight: 1 + {{- end }} +{{- end }} diff --git a/helm/defectdojo/templates/external-secret.yaml b/helm/defectdojo/templates/external-secret.yaml new file mode 100644 index 00000000000..4f3070430cc --- /dev/null +++ b/helm/defectdojo/templates/external-secret.yaml @@ -0,0 +1,37 @@ +{{- if .Values.externalSecret.enabled }} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} + labels: + defectdojo.org/component: django + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- with .Values.externalSecret.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.extraAnnotations .Values.externalSecret.annotations }} + annotations: + {{- range $key, $value := .Values.extraAnnotations }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- with .Values.externalSecret.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + refreshInterval: {{ .Values.externalSecret.refreshInterval | default "1h0m0s" }} + secretStoreRef: + {{- toYaml .Values.externalSecret.secretStoreRef | nindent 4 }} + target: + name: {{ .Values.externalSecret.targetSecretName }} + data: + {{- toYaml .Values.externalSecret.data | nindent 4 }} +{{- end }} diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 792930707e4..26b9b089c4a 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -13,6 +13,28 @@ createSecret: false createValkeySecret: false # -- create postgresql secret in defectdojo chart, outside of postgresql chart createPostgresqlSecret: false + +# -- External Secrets Operator integration +externalSecret: + # -- Enable the ExternalSecret resource + enabled: false + labels: {} + annotations: {} + # -- How often to refresh the secret from the external store + refreshInterval: 1h0m0s + # -- Reference to a SecretStore or ClusterSecretStore + secretStoreRef: + name: "" + kind: "" + # -- Name of the Kubernetes Secret created by ESO + targetSecretName: "" + # -- Data mappings from the external store + data: [] + # - secretKey: DD_ADMIN_PASSWORD + # remoteRef: + # key: my-vault-path + # property: admin-password + # -- Track configuration (trackConfig): will automatically respin application pods in case of config changes detection # can be: # 1. disabled (default) @@ -372,6 +394,21 @@ django: # `nginx.ingress.kubernetes.io/proxy-read-timeout: "1800"` # `nginx.ingress.kubernetes.io/proxy-send-timeout: "1800"` annotations: {} + # -- Kubernetes Gateway API HTTPRoute configuration (alternative to Ingress) + httpRoute: + enabled: false + labels: {} + annotations: {} + parentRefs: [] + # - name: my-gateway + # namespace: default + hostnames: [] + # - defectdojo.example.com + rules: [] + # - matches: + # - path: + # type: PathPrefix + # value: / nginx: # -- If empty, uses values from images.nginx.image image: