From 314c18c14151fcf4d68d2c35edbcf64ecba83533 Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 13:46:20 -0700 Subject: [PATCH 1/6] Allow a user provided jwt secret --- .github/workflows/ci.yml | 8 ++++++++ deploy/rustfs-operator/README.md | 19 +++++++++++++++++++ .../templates/console-deployment.yaml | 8 ++++++-- .../templates/console-secret.yaml | 2 +- deploy/rustfs-operator/values.schema.json | 6 ++++++ deploy/rustfs-operator/values.yaml | 6 ++++++ 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85174126..36d03502 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,6 +142,14 @@ jobs: > /tmp/helm-cosi-custom-rbac.yaml ! grep -q "cosi-driver-clusterrole" /tmp/helm-cosi-custom-rbac.yaml + # Existing console Secret: chart must not create its own Secret and the + # Deployment must reference the supplied name. + helm template test deploy/rustfs-operator \ + --set console.existingSecret=my-console-jwt \ + > /tmp/helm-console-existing-secret.yaml + ! grep -q "console-secret" /tmp/helm-console-existing-secret.yaml + grep -q "name: my-console-jwt" /tmp/helm-console-existing-secret.yaml + - name: Check release metadata run: make release-metadata-check diff --git a/deploy/rustfs-operator/README.md b/deploy/rustfs-operator/README.md index 2bae0137..d20a837f 100755 --- a/deploy/rustfs-operator/README.md +++ b/deploy/rustfs-operator/README.md @@ -662,6 +662,25 @@ Before rolling back to a release without server-side sessions, scale the Console Deployment to zero, perform the rollback, then restore one replica so the two cookie formats never overlap. +### Console JWT secret + +The Console encrypts in-process session data with a `jwt-secret`. By default the +chart generates a random secret on first install and stores it in +`-console-secret` in the operator namespace, reusing it across upgrades. +To manage the secret value outside the chart, either set `console.jwtSecret` or +reference an existing Secret: + +```yaml +console: + existingSecret: my-console-jwt +``` + +The referenced Secret must live in the operator namespace and contain a +`jwt-secret` key (generate one with `openssl rand -base64 32`). When +`console.existingSecret` is set, the chart does not create its own Console Secret +and the Console Deployment reads `JWT_SECRET` from the existing Secret. +`console.existingSecret` and `console.jwtSecret` are mutually exclusive. + ### Backend CORS (when frontend is on a different host) If the frontend is served from another host (e.g. `https://ui.example.com`) and the API at `https://api.example.com`, set allowed origins on the console backend: diff --git a/deploy/rustfs-operator/templates/console-deployment.yaml b/deploy/rustfs-operator/templates/console-deployment.yaml index 9de4cf38..7dc735e5 100755 --- a/deploy/rustfs-operator/templates/console-deployment.yaml +++ b/deploy/rustfs-operator/templates/console-deployment.yaml @@ -17,6 +17,10 @@ {{- if and .Values.console.enabled (ne (toString .Values.console.replicas) "1") -}} {{- fail "console.replicas must be 1 because Console sessions are stored in process" -}} {{- end -}} +{{- if and .Values.console.enabled .Values.console.existingSecret .Values.console.jwtSecret -}} +{{- fail "console.existingSecret and console.jwtSecret are mutually exclusive; set only one" -}} +{{- end -}} +{{- $consoleSecretName := .Values.console.existingSecret | default (printf "%s-console-secret" (include "rustfs-operator.fullname" .)) -}} {{- if .Values.console.enabled -}} apiVersion: apps/v1 kind: Deployment @@ -46,7 +50,7 @@ spec: app.kubernetes.io/component: console annotations: # Force reload on secret changes - checksum/secret: {{ include (print $.Template.BasePath "/console-secret.yaml") . | sha256sum }} + checksum/secret: {{ if .Values.console.existingSecret }}{{ .Values.console.existingSecret | sha256sum }}{{ else }}{{ include (print $.Template.BasePath "/console-secret.yaml") . | sha256sum }}{{ end }} spec: serviceAccountName: {{ include "rustfs-operator.consoleServiceAccountName" . }} {{- if $openShiftEnabled }} @@ -73,7 +77,7 @@ spec: - name: JWT_SECRET valueFrom: secretKeyRef: - name: {{ include "rustfs-operator.fullname" . }}-console-secret + name: {{ $consoleSecretName }} key: jwt-secret {{- with .Values.console.bindAddress }} - name: CONSOLE_BIND_ADDRESS diff --git a/deploy/rustfs-operator/templates/console-secret.yaml b/deploy/rustfs-operator/templates/console-secret.yaml index 8186c0db..1e1325c2 100755 --- a/deploy/rustfs-operator/templates/console-secret.yaml +++ b/deploy/rustfs-operator/templates/console-secret.yaml @@ -1,4 +1,4 @@ -{{- if .Values.console.enabled -}} +{{- if and .Values.console.enabled (not .Values.console.existingSecret) -}} {{- $secretName := printf "%s-console-secret" (include "rustfs-operator.fullname" .) -}} {{- $namespace := include "rustfs-operator.namespace" . -}} {{- $existingSecret := lookup "v1" "Secret" $namespace $secretName -}} diff --git a/deploy/rustfs-operator/values.schema.json b/deploy/rustfs-operator/values.schema.json index ead0aaf4..9eef5915 100644 --- a/deploy/rustfs-operator/values.schema.json +++ b/deploy/rustfs-operator/values.schema.json @@ -68,6 +68,12 @@ "console": { "type": "object", "properties": { + "existingSecret": { + "type": "string", + "maxLength": 253, + "pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", + "description": "Name of a pre-existing Secret in the operator namespace containing the key jwt-secret; when set the chart does not create its own Console Secret." + }, "loginAdmission": { "$ref": "#/definitions/admission" } diff --git a/deploy/rustfs-operator/values.yaml b/deploy/rustfs-operator/values.yaml index 11002a9a..80a35a34 100755 --- a/deploy/rustfs-operator/values.yaml +++ b/deploy/rustfs-operator/values.yaml @@ -222,6 +222,12 @@ console: # Generate with: openssl rand -base64 32 jwtSecret: "" + # Name of a pre-existing Secret in the operator namespace that contains the key + # "jwt-secret" used to encrypt in-process Console session data. When set, the chart + # does not create its own Console Secret and the Console Deployment references this + # Secret directly. Mutually exclusive with console.jwtSecret. + existingSecret: "" + image: # Console uses the same image as operator repository: rustfs/operator From de5c8be34fc45bd3e347674468b196f872378b7c Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 13:57:09 -0700 Subject: [PATCH 2/6] _hepler.tpl to reduce inline helm templating --- deploy/rustfs-operator/templates/_helpers.tpl | 13 +++++++++++++ .../templates/console-deployment.yaml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/deploy/rustfs-operator/templates/_helpers.tpl b/deploy/rustfs-operator/templates/_helpers.tpl index c7dfdb82..3e7cb841 100755 --- a/deploy/rustfs-operator/templates/_helpers.tpl +++ b/deploy/rustfs-operator/templates/_helpers.tpl @@ -113,3 +113,16 @@ Create the name of the COSI driver service account to use {{- default "default" .Values.cosiDriver.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Checksum of the Console JWT secret source, used to force a rollout when the +secret changes. When console.existingSecret is set, checksum the referenced +Secret name; otherwise checksum the chart-managed Console Secret template. +*/}} +{{- define "rustfs-operator.consoleSecretChecksum" -}} +{{- if .Values.console.existingSecret -}} +{{- .Values.console.existingSecret | sha256sum -}} +{{- else -}} +{{- include (print $.Template.BasePath "/console-secret.yaml") . | sha256sum -}} +{{- end -}} +{{- end }} diff --git a/deploy/rustfs-operator/templates/console-deployment.yaml b/deploy/rustfs-operator/templates/console-deployment.yaml index 7dc735e5..4f03293f 100755 --- a/deploy/rustfs-operator/templates/console-deployment.yaml +++ b/deploy/rustfs-operator/templates/console-deployment.yaml @@ -50,7 +50,7 @@ spec: app.kubernetes.io/component: console annotations: # Force reload on secret changes - checksum/secret: {{ if .Values.console.existingSecret }}{{ .Values.console.existingSecret | sha256sum }}{{ else }}{{ include (print $.Template.BasePath "/console-secret.yaml") . | sha256sum }}{{ end }} + checksum/secret: {{ include "rustfs-operator.consoleSecretChecksum" . }} spec: serviceAccountName: {{ include "rustfs-operator.consoleServiceAccountName" . }} {{- if $openShiftEnabled }} From eceb927a092b221f9595ffa2eb5952749d22502b Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 14:01:41 -0700 Subject: [PATCH 3/6] readme note --- deploy/rustfs-operator/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deploy/rustfs-operator/README.md b/deploy/rustfs-operator/README.md index d20a837f..1167e1f1 100755 --- a/deploy/rustfs-operator/README.md +++ b/deploy/rustfs-operator/README.md @@ -681,6 +681,11 @@ The referenced Secret must live in the operator namespace and contain a and the Console Deployment reads `JWT_SECRET` from the existing Secret. `console.existingSecret` and `console.jwtSecret` are mutually exclusive. +> Note: externally managed Secrets do not automatically trigger a Console +> restart when the value of that Secret changes. Rotate the Secret value and +> restart the Console Deployment manually (e.g. `kubectl rollout restart`) +> for the new `jwt-secret` to take effect. + ### Backend CORS (when frontend is on a different host) If the frontend is served from another host (e.g. `https://ui.example.com`) and the API at `https://api.example.com`, set allowed origins on the console backend: From 6d1292fa614fac37759d14b2f80e0f492341978f Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 14:20:14 -0700 Subject: [PATCH 4/6] self review fixes --- deploy/rustfs-operator/templates/console-deployment.yaml | 2 +- deploy/rustfs-operator/values.schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/rustfs-operator/templates/console-deployment.yaml b/deploy/rustfs-operator/templates/console-deployment.yaml index 4f03293f..73a674f6 100755 --- a/deploy/rustfs-operator/templates/console-deployment.yaml +++ b/deploy/rustfs-operator/templates/console-deployment.yaml @@ -77,7 +77,7 @@ spec: - name: JWT_SECRET valueFrom: secretKeyRef: - name: {{ $consoleSecretName }} + name: {{ $consoleSecretName | quote }} key: jwt-secret {{- with .Values.console.bindAddress }} - name: CONSOLE_BIND_ADDRESS diff --git a/deploy/rustfs-operator/values.schema.json b/deploy/rustfs-operator/values.schema.json index 9eef5915..07a918fb 100644 --- a/deploy/rustfs-operator/values.schema.json +++ b/deploy/rustfs-operator/values.schema.json @@ -71,7 +71,7 @@ "existingSecret": { "type": "string", "maxLength": 253, - "pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", + "pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", "description": "Name of a pre-existing Secret in the operator namespace containing the key jwt-secret; when set the chart does not create its own Console Secret." }, "loginAdmission": { From 6ff6dea71fce05afb1228fd27cb435d3606641e3 Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 14:21:59 -0700 Subject: [PATCH 5/6] schema tweak --- deploy/rustfs-operator/values.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/rustfs-operator/values.schema.json b/deploy/rustfs-operator/values.schema.json index 07a918fb..db3959a6 100644 --- a/deploy/rustfs-operator/values.schema.json +++ b/deploy/rustfs-operator/values.schema.json @@ -71,7 +71,7 @@ "existingSecret": { "type": "string", "maxLength": 253, - "pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + "pattern": "^$|^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$", "description": "Name of a pre-existing Secret in the operator namespace containing the key jwt-secret; when set the chart does not create its own Console Secret." }, "loginAdmission": { From 3db71eb9367339a8794f923c4fc900f28ad559af Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sun, 4 Oct 2026 14:25:45 -0700 Subject: [PATCH 6/6] ci tweak for name changes --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36d03502..b27a70fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -148,7 +148,7 @@ jobs: --set console.existingSecret=my-console-jwt \ > /tmp/helm-console-existing-secret.yaml ! grep -q "console-secret" /tmp/helm-console-existing-secret.yaml - grep -q "name: my-console-jwt" /tmp/helm-console-existing-secret.yaml + grep -q 'name: "my-console-jwt"' /tmp/helm-console-existing-secret.yaml - name: Check release metadata run: make release-metadata-check