From b5a99a1b74db47f41f6014919bd0f3c4676b6df8 Mon Sep 17 00:00:00 2001 From: Paulo Roberto Date: Thu, 21 May 2026 15:00:07 -0300 Subject: [PATCH 1/2] feat(helm/studio): add opt-in ExternalSecret support for AWS Secrets Manager When externalSecret.enabled=true, the chart creates a namespace-scoped SecretStore and an ExternalSecret using dataFrom so every key in the SM JSON becomes an env var automatically, with no per-key listing required. Backward compatible: disabled by default. --- .../helm/studio/templates/externalsecret.yaml | 35 +++++++++++++++++++ deploy/helm/studio/templates/secret.yaml | 2 +- deploy/helm/studio/values.yaml | 14 ++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 deploy/helm/studio/templates/externalsecret.yaml diff --git a/deploy/helm/studio/templates/externalsecret.yaml b/deploy/helm/studio/templates/externalsecret.yaml new file mode 100644 index 0000000000..3c4f1aab85 --- /dev/null +++ b/deploy/helm/studio/templates/externalsecret.yaml @@ -0,0 +1,35 @@ +{{- if .Values.externalSecret.enabled }} +--- +apiVersion: external-secrets.io/v1 +kind: SecretStore +metadata: + name: {{ .Values.externalSecret.secretStoreName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "chart-deco-studio.labels" . | nindent 4 }} +spec: + provider: + aws: + service: SecretsManager + region: {{ .Values.externalSecret.provider.aws.region }} +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: {{ include "chart-deco-studio.fullname" . }}-secrets + namespace: {{ .Release.Namespace }} + labels: + {{- include "chart-deco-studio.labels" . | nindent 4 }} +spec: + refreshInterval: {{ .Values.externalSecret.refreshInterval | quote }} + secretStoreRef: + name: {{ .Values.externalSecret.secretStoreName }} + kind: SecretStore + target: + name: {{ include "chart-deco-studio.secretName" . }} + creationPolicy: Owner + deletionPolicy: Retain + dataFrom: + - extract: + key: {{ required "externalSecret.secretPath is required when externalSecret.enabled=true" .Values.externalSecret.secretPath }} +{{- end }} diff --git a/deploy/helm/studio/templates/secret.yaml b/deploy/helm/studio/templates/secret.yaml index 943cc325fc..122ca8efa6 100644 --- a/deploy/helm/studio/templates/secret.yaml +++ b/deploy/helm/studio/templates/secret.yaml @@ -1,4 +1,4 @@ -{{- if not .Values.secret.secretName }} +{{- if and (not .Values.secret.secretName) (not .Values.externalSecret.enabled) }} apiVersion: v1 kind: Secret metadata: diff --git a/deploy/helm/studio/values.yaml b/deploy/helm/studio/values.yaml index cebf18450f..ec31eda93c 100644 --- a/deploy/helm/studio/values.yaml +++ b/deploy/helm/studio/values.yaml @@ -74,6 +74,20 @@ secret: # Generate with: openssl rand -base64 32 ENCRYPTION_KEY: "" +# ExternalSecret — pull all values from AWS Secrets Manager via external-secrets operator. +# When enabled, creates a namespace-scoped SecretStore and an ExternalSecret using dataFrom +# so every key in the SM JSON becomes an env var automatically. +# Requires: external-secrets operator installed on the cluster. +# Incompatible with: secret.secretName (both reference the same target Secret name). +externalSecret: + enabled: false + # secretPath: "" # Required when enabled. SM secret key path. + secretStoreName: "aws-secrets-manager" + refreshInterval: "1h" + provider: + aws: + region: "sa-east-1" + volumes: [] # - name: foo # secret: From dad6a5b668f869dddf596db84c407863d2514a41 Mon Sep 17 00:00:00 2001 From: Paulo Roberto Date: Thu, 21 May 2026 15:01:46 -0300 Subject: [PATCH 2/2] fix(helm/studio): guard ExternalSecret against secret.secretName conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ExternalSecret target is now always the chart-managed name ({fullname}-secrets), never secret.secretName — prevents silent takeover of existing Secrets - Validation fails if both externalSecret.enabled=true and secret.secretName are set --- deploy/helm/studio/templates/_helpers.tpl | 12 ++++++++++++ deploy/helm/studio/templates/externalsecret.yaml | 4 ++-- deploy/helm/studio/templates/validations.yaml | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/deploy/helm/studio/templates/_helpers.tpl b/deploy/helm/studio/templates/_helpers.tpl index d3eb01d605..e3acd3c457 100644 --- a/deploy/helm/studio/templates/_helpers.tpl +++ b/deploy/helm/studio/templates/_helpers.tpl @@ -178,6 +178,18 @@ Validate OTel collector/S3 configuration. {{- end }} {{- end }} +{{/* +Validates ExternalSecret configuration. +*/}} +{{- define "chart-deco-studio.validateExternalSecret" -}} +{{- if and .Values.externalSecret.enabled .Values.secret.secretName }} +{{- fail "chart-deco-studio: externalSecret.enabled=true and secret.secretName are mutually exclusive — remove secret.secretName when using ExternalSecret" -}} +{{- end }} +{{- if and .Values.externalSecret.enabled (not .Values.externalSecret.secretPath) }} +{{- fail "chart-deco-studio: externalSecret.secretPath is required when externalSecret.enabled=true" -}} +{{- end }} +{{- end }} + {{/* Formats OTEL headers map as key=value,key2=value2 format. */}} diff --git a/deploy/helm/studio/templates/externalsecret.yaml b/deploy/helm/studio/templates/externalsecret.yaml index 3c4f1aab85..501475b799 100644 --- a/deploy/helm/studio/templates/externalsecret.yaml +++ b/deploy/helm/studio/templates/externalsecret.yaml @@ -26,10 +26,10 @@ spec: name: {{ .Values.externalSecret.secretStoreName }} kind: SecretStore target: - name: {{ include "chart-deco-studio.secretName" . }} + name: {{ include "chart-deco-studio.fullname" . }}-secrets creationPolicy: Owner deletionPolicy: Retain dataFrom: - extract: - key: {{ required "externalSecret.secretPath is required when externalSecret.enabled=true" .Values.externalSecret.secretPath }} + key: {{ .Values.externalSecret.secretPath }} {{- end }} diff --git a/deploy/helm/studio/templates/validations.yaml b/deploy/helm/studio/templates/validations.yaml index 7373c68694..65cf7b1119 100644 --- a/deploy/helm/studio/templates/validations.yaml +++ b/deploy/helm/studio/templates/validations.yaml @@ -3,4 +3,5 @@ This file only runs chart-level validations and renders no resources. */ -}} {{- include "chart-deco-studio.validate" . -}} {{- include "chart-deco-studio.validateOtel" . -}} +{{- include "chart-deco-studio.validateExternalSecret" . -}}