From a31f289da21badec5c076e857a481f1dccf425c1 Mon Sep 17 00:00:00 2001 From: Kyle Felter Date: Fri, 31 Jul 2026 14:15:25 -0500 Subject: [PATCH 1/2] fix(helm): Generate strong Temporal payload encryption key --- .../nico-rest-common/templates/secrets.yaml | 12 ++++++- .../nico-rest-common/tests/secrets_test.yaml | 32 +++++++++++++++++++ .../charts/nico-rest-common/values.yaml | 5 +-- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml diff --git a/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml b/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml index fc9445eaf6..90e3f6004c 100644 --- a/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml +++ b/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml @@ -2,6 +2,16 @@ # SPDX-License-Identifier: Apache-2.0 {{- if .Values.secrets.create }} +{{- $temporalEncryptionKey := .Values.secrets.temporalEncryptionKey.value }} +{{- if not $temporalEncryptionKey }} + {{- $existingSecret := lookup "v1" "Secret" (include "nico-rest-common.namespace" .) "temporal-encryption-key" }} + {{- $existingKey := dig "data" "temporal-encryption-key" "" $existingSecret }} + {{- if $existingKey }} + {{- $temporalEncryptionKey = $existingKey | b64dec }} + {{- else }} + {{- $temporalEncryptionKey = randBytes 32 }} + {{- end }} +{{- end }} # db-creds and image-pull-secret are annotated as pre-install / pre-upgrade # hooks (weight -10) because the nico-rest-db migration Job runs as its own # pre-install hook at weight -5 and needs both to exist before it starts. @@ -45,7 +55,7 @@ metadata: {{- include "nico-rest-common.labels" . | nindent 4 }} type: Opaque stringData: - temporal-encryption-key: {{ .Values.secrets.temporalEncryptionKey.value | quote }} + temporal-encryption-key: {{ $temporalEncryptionKey | quote }} --- apiVersion: v1 kind: Secret diff --git a/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml b/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml new file mode 100644 index 0000000000..dd225110ee --- /dev/null +++ b/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +suite: common secrets +templates: + - secrets.yaml +tests: + - it: generates the Temporal encryption key from 32 random bytes by default + asserts: + - matchRegex: + path: stringData.temporal-encryption-key + pattern: ^[A-Za-z0-9+/]{43}=$ + documentIndex: 2 + + - it: uses an explicitly configured Temporal encryption key + set: + secrets: + temporalEncryptionKey: + value: configured-key + asserts: + - equal: + path: stringData.temporal-encryption-key + value: configured-key + documentIndex: 2 + + - it: omits all Secrets when creation is disabled + set: + secrets: + create: false + asserts: + - hasDocuments: + count: 0 diff --git a/helm/rest/nico-rest/charts/nico-rest-common/values.yaml b/helm/rest/nico-rest/charts/nico-rest-common/values.yaml index 2eb046b1b2..2591188589 100644 --- a/helm/rest/nico-rest/charts/nico-rest-common/values.yaml +++ b/helm/rest/nico-rest/charts/nico-rest-common/values.yaml @@ -16,8 +16,9 @@ secrets: # -- Keycloak client secret. Replace in production. value: "nico-local-secret" temporalEncryptionKey: - # -- Temporal payload encryption key. Replace in production. - value: "local-dev" + # -- Temporal payload encryption key. When empty, Helm generates a key from + # 32 random bytes on install and reuses the existing Secret on upgrade. + value: "" imagePullSecret: # -- base64-encoded docker config JSON. Default is valid empty auth placeholder ({"auths":{}}). # Replace with real credentials for private registries. From 577bb43d76d4cc0c5e905f88a3ac575bf0744764 Mon Sep 17 00:00:00 2001 From: Kyle Felter Date: Fri, 31 Jul 2026 20:11:44 -0500 Subject: [PATCH 2/2] fix(helm): Fail closed when Temporal key is missing --- .../nico-rest-common/templates/secrets.yaml | 4 ++- .../nico-rest-common/tests/secrets_test.yaml | 33 +++++++++++++++++++ .../charts/nico-rest-common/values.yaml | 7 ++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml b/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml index 90e3f6004c..ead554ea22 100644 --- a/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml +++ b/helm/rest/nico-rest/charts/nico-rest-common/templates/secrets.yaml @@ -8,8 +8,10 @@ {{- $existingKey := dig "data" "temporal-encryption-key" "" $existingSecret }} {{- if $existingKey }} {{- $temporalEncryptionKey = $existingKey | b64dec }} - {{- else }} + {{- else if .Release.IsInstall }} {{- $temporalEncryptionKey = randBytes 32 }} + {{- else }} + {{- fail "nico-rest-common requires an existing or explicitly configured Temporal encryption key on upgrade" }} {{- end }} {{- end }} # db-creds and image-pull-secret are annotated as pre-install / pre-upgrade diff --git a/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml b/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml index dd225110ee..5e180abba2 100644 --- a/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml +++ b/helm/rest/nico-rest/charts/nico-rest-common/tests/secrets_test.yaml @@ -23,6 +23,39 @@ tests: value: configured-key documentIndex: 2 + - it: reuses the existing Temporal encryption key on upgrade + release: + namespace: nico-rest + upgrade: true + kubernetesProvider: + scheme: + "v1/Secret": + gvr: + version: v1 + resource: secrets + namespaced: true + objects: + - apiVersion: v1 + kind: Secret + metadata: + name: temporal-encryption-key + namespace: nico-rest + data: + temporal-encryption-key: ZXhpc3Rpbmcta2V5 + asserts: + - equal: + path: stringData.temporal-encryption-key + value: existing-key + documentIndex: 2 + + - it: fails an upgrade when the Temporal encryption key is unavailable + release: + namespace: nico-rest + upgrade: true + asserts: + - failedTemplate: + errorMessage: nico-rest-common requires an existing or explicitly configured Temporal encryption key on upgrade + - it: omits all Secrets when creation is disabled set: secrets: diff --git a/helm/rest/nico-rest/charts/nico-rest-common/values.yaml b/helm/rest/nico-rest/charts/nico-rest-common/values.yaml index 2591188589..5ef4eb653b 100644 --- a/helm/rest/nico-rest/charts/nico-rest-common/values.yaml +++ b/helm/rest/nico-rest/charts/nico-rest-common/values.yaml @@ -16,8 +16,11 @@ secrets: # -- Keycloak client secret. Replace in production. value: "nico-local-secret" temporalEncryptionKey: - # -- Temporal payload encryption key. When empty, Helm generates a key from - # 32 random bytes on install and reuses the existing Secret on upgrade. + # -- Temporal payload encryption key. Default is empty. When Secret creation + # is enabled, an explicit value takes precedence over an existing Secret. An + # empty value reuses the existing Secret, generates 32 random bytes on a fresh + # install, or fails an upgrade when no existing key is available. Setting + # secrets.create to false disables this resolution. value: "" imagePullSecret: # -- base64-encoded docker config JSON. Default is valid empty auth placeholder ({"auths":{}}).