From 3b5c64e045b3ac193976d34f34754c978bd2c699 Mon Sep 17 00:00:00 2001 From: Ariel Lahiany Date: Tue, 25 Aug 2026 09:38:06 +0300 Subject: [PATCH] feat: render password_hash for users users.toml supports password_hash, a PostgreSQL SCRAM verifier used in place of a plaintext password, but the users template had no branch for it. The key was silently dropped: the chart rendered a [[users]] entry with no credential at all, and the omission only surfaced later as a client authentication failure. This matters when the backend connection authenticates without a password -- serverAuth: rds_iam, or a Vault-issued credential -- because the frontend password is then the only secret left in users.toml, and a SCRAM verifier is the one form of it that is safe to keep in version control. The verifier cannot be replayed to authenticate, so it can live in values.yaml while the password itself never enters the repository. Rendered as a separate conditional rather than another branch of the existing passwords/password if-chain, so a user may carry a verifier alongside other settings without the chain's ordering deciding which one wins. Covered by test/values-password-hash.yaml, asserting both that password_hash reaches users.toml and that no plaintext password line is emitted for a hash-only user. The verifier in the fixture is generated from a throwaway password with a fixed salt and is not a credential for anything. Co-Authored-By: Claude Opus 5 (1M context) --- templates/secrets.yaml | 3 +++ test/test.sh | 23 +++++++++++++++++++++++ test/values-password-hash.yaml | 17 +++++++++++++++++ values.yaml | 13 +++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 test/values-password-hash.yaml diff --git a/templates/secrets.yaml b/templates/secrets.yaml index 80c48f0..e4f423c 100644 --- a/templates/secrets.yaml +++ b/templates/secrets.yaml @@ -8,6 +8,9 @@ passwords = [{{ range $i, $p := .passwords }}{{ if $i }}, {{ end }}{{ $p | quote {{- else if .password }} password = {{ .password | quote }} {{- end }} +{{- if .passwordHash }} +password_hash = {{ .passwordHash | quote }} +{{- end }} {{- if .poolSize }} pool_size = {{ .poolSize }} {{- end }} diff --git a/test/test.sh b/test/test.sh index 5b7b938..c6e2381 100755 --- a/test/test.sh +++ b/test/test.sh @@ -37,5 +37,28 @@ else exit 1 fi +# Validate password hash renders valid TOML +echo "" +echo "==> Validating password hash TOML output..." +users_toml=$(helm template test-release "$CHART_DIR" -f "$TEST_DIR/values-password-hash.yaml" \ + | yq -r 'select(.kind == "Secret" and .metadata.name == "test-release-pgdog") | .data["users.toml"]' \ + | base64 -d) + +if echo "$users_toml" | grep -q 'password_hash = "SCRAM-SHA-256\$4096:'; then + echo " password hash rendered correctly" +else + echo " FAIL: password hash not rendered correctly" + echo " Got: $users_toml" + exit 1 +fi + +if echo "$users_toml" | grep -q '^password = '; then + echo " FAIL: plaintext password rendered for a hash-only user" + echo " Got: $users_toml" + exit 1 +else + echo " no plaintext password rendered" +fi + echo "" echo "==> All tests passed!" diff --git a/test/values-password-hash.yaml b/test/values-password-hash.yaml new file mode 100644 index 0000000..b10033c --- /dev/null +++ b/test/values-password-hash.yaml @@ -0,0 +1,17 @@ +# Test a SCRAM verifier in place of a plaintext password. +# PgDog requires passwordless backend auth when password_hash is used. +# +# The verifier below is generated from the throwaway password +# "pgdog-chart-test-password" with a fixed 16-byte salt, purely so this fixture +# has a well-formed value to render. It is not a credential for anything. +databases: + - name: primary + host: postgres-primary.example.com + port: 5432 + +users: + - name: app_user + database: primary + passwordHash: "SCRAM-SHA-256$4096:AAECAwQFBgcICQoLDA0ODw==$4td+UR3YAWZ1KVIzL/2kUznOtnXa9WfGSd43hLG6MlE=:tpNtjd9V1KIFupdow3F2SEDGpKo53k/JYt6M2m5jtvo=" + serverUser: app_role + serverAuth: rds_iam diff --git a/values.yaml b/values.yaml index f218531..b7738a9 100644 --- a/values.yaml +++ b/values.yaml @@ -233,6 +233,19 @@ databases: [] # users contains the list of user entries in users.toml # Supports all arguments from users.toml. Arguments are named in # camelCase format. +# +# passwordHash accepts a PostgreSQL SCRAM verifier (the value stored in +# pg_authid.rolpassword) instead of a plaintext password, so client logins can +# be validated without keeping the password in users.toml. PgDog requires the +# backend connection to authenticate without a password when it is used, e.g. +# serverAuth: rds_iam. +# +# users: +# - name: app_user +# database: primary +# passwordHash: "SCRAM-SHA-256$4096:$:" +# serverUser: app_role +# serverAuth: rds_iam users: [] # mirrors contains a list of databases to replicate traffic from/to.