From 3e002ff6855166d3d171890d36a0985e28a584cf Mon Sep 17 00:00:00 2001 From: Guilherme Moreira Rodrigues Date: Fri, 31 Jul 2026 18:08:00 -0300 Subject: [PATCH 1/2] fix(common): streaming.secret requires SASL username with the mechanism The SASL fail-fast only checked STREAMING_SASL_PASSWORD; a mechanism configured with a password but no username still rendered (STREAMING_SASL_USERNAME: "") and crashed at boot, since lib-streaming rejects a SASL mechanism without BOTH credentials. Accept the resolved saslUsername (ConfigMap value, configmap.STREAMING_SASL_USERNAME -> global.streaming.saslUsername precedence) and fail the render when a mechanism is set without it. Usage example updated to pass saslUsername. --- charts/lerian-common/templates/_streaming.tpl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/charts/lerian-common/templates/_streaming.tpl b/charts/lerian-common/templates/_streaming.tpl index f6ac1a054..33ed33891 100644 --- a/charts/lerian-common/templates/_streaming.tpl +++ b/charts/lerian-common/templates/_streaming.tpl @@ -110,14 +110,16 @@ matching `data:`/`stringData:` key: "secretName" (include "midaz.ledger.fullname" .) "valuesPrefix" "ledger.secrets." "mode" "data" "enabled" true "useExistingSecret" .Values.ledger.useExistingSecret - "saslMechanism" (dig "streaming" "saslMechanism" "" (.Values.global | default dict)))) }} + "saslMechanism" (dig "streaming" "saslMechanism" "" (.Values.global | default dict)) + "saslUsername" (dig "streaming" "saslUsername" "" (.Values.global | default dict)))) }} {{- . | nindent 2 }} {{- end }} Inputs: context, secrets, secretName, valuesPrefix, mode, enabled (bool — STREAMING_ENABLED), useExistingSecret (bool — skip entirely when true), - saslMechanism (string — when non-empty, SASL_PASSWORD becomes required). + saslMechanism (string — when non-empty, both SASL_USERNAME and SASL_PASSWORD become required), + saslUsername (string — the resolved STREAMING_SASL_USERNAME; required when saslMechanism is set). ------------------------------------------------------------------------------ */}} {{- define "lerian-common.streaming.secret" -}} @@ -126,6 +128,14 @@ Inputs: context, secrets, secretName, valuesPrefix, mode, {{- $b64 := eq (.mode | default "stringData") "data" -}} {{- $ns := .context.Release.Namespace -}} {{- $lines := list -}} +{{- /* STREAMING_SASL_USERNAME — required (with the password) whenever a SASL mechanism + is set; lib-streaming rejects a mechanism without BOTH credentials. The username is a + ConfigMap value (not a secret), resolved by the caller with the same precedence + (configmap.STREAMING_SASL_USERNAME -> global.streaming.saslUsername) and passed here so + the render fails fast instead of shipping a boot-crashing config. */ -}} +{{- if and .saslMechanism (not .saslUsername) -}} +{{- fail (printf "\n[lerian-common] Value required but empty: STREAMING_SASL_USERNAME\n a SASL mechanism (%s) is set, which requires both a username and a password.\n set: configmap.STREAMING_SASL_USERNAME (or global.streaming.saslUsername)\n" .saslMechanism) -}} +{{- end -}} {{- /* STREAMING_SASL_PASSWORD — required only when a SASL mechanism is set */ -}} {{- $sasl := index $s "STREAMING_SASL_PASSWORD" -}} {{- if and .saslMechanism (not $sasl) -}} From 2bbd552a16871104776af0286f2047da162eecc0 Mon Sep 17 00:00:00 2001 From: Guilherme Moreira Rodrigues Date: Fri, 31 Jul 2026 18:48:26 -0300 Subject: [PATCH 2/2] docs(common): usage example resolves SASL mechanism/username with configmap precedence The streaming.secret usage example read saslMechanism/saslUsername from global only, so a copied consumer would bypass validation on a ConfigMap-only mechanism and hit a false failure on a ConfigMap-only username. Show the configmap-over-global hasKey resolution (matching streaming.env and the real midaz call sites). --- charts/lerian-common/templates/_streaming.tpl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/charts/lerian-common/templates/_streaming.tpl b/charts/lerian-common/templates/_streaming.tpl index 33ed33891..e30da21f0 100644 --- a/charts/lerian-common/templates/_streaming.tpl +++ b/charts/lerian-common/templates/_streaming.tpl @@ -105,13 +105,20 @@ on install AND upgrade (these values are operator/Vault-provided, never generate matching `data:`/`stringData:` key: # STREAMING SECRETS + # Resolve mechanism + username with the SAME configmap-over-global precedence the + # ConfigMap uses (streaming.env), so a ConfigMap-only mechanism is still validated and + # a ConfigMap-only username does not cause a false failure. An explicit empty ConfigMap + # value is preserved (hasKey) so validation still fails when it should. + {{- $saslMech := (((.Values.global | default dict).streaming | default dict).saslMechanism | default "") }} + {{- if hasKey .Values.ledger.configmap "STREAMING_SASL_MECHANISM" }}{{- $saslMech = index .Values.ledger.configmap "STREAMING_SASL_MECHANISM" }}{{- end }} + {{- $saslUser := (((.Values.global | default dict).streaming | default dict).saslUsername | default "") }} + {{- if hasKey .Values.ledger.configmap "STREAMING_SASL_USERNAME" }}{{- $saslUser = index .Values.ledger.configmap "STREAMING_SASL_USERNAME" }}{{- end }} {{- with (include "lerian-common.streaming.secret" (dict "context" . "secrets" .Values.ledger.secrets "secretName" (include "midaz.ledger.fullname" .) "valuesPrefix" "ledger.secrets." "mode" "data" "enabled" true "useExistingSecret" .Values.ledger.useExistingSecret - "saslMechanism" (dig "streaming" "saslMechanism" "" (.Values.global | default dict)) - "saslUsername" (dig "streaming" "saslUsername" "" (.Values.global | default dict)))) }} + "saslMechanism" $saslMech "saslUsername" $saslUser)) }} {{- . | nindent 2 }} {{- end }}