Description
The gateway-helm-chart lets an operator configure the controller's external database (postgres/sqlserver) either via a full dsn or via individual host/port/database/user fields with the password injected separately from a Secret (passwordSecretRef). These two modes are mutually exclusive, but the chart neither enforces nor clearly documents that — leading to silent misconfiguration.
Root cause in the controller: buildPostgresDSN (gateway/gateway-controller/pkg/storage/postgres.go:140) and buildSQLServerDSN (pkg/storage/sqlserver.go) return the dsn as-is when it is non-empty and never merge the separately-configured Password. The password field is only used when dsn is empty. At the chart level, gateway-config.yaml renders the password = '{{ env … }}' line only in the non-DSN branch, so when dsn is set the injected APIP_GW_CONTROLLER_STORAGE_POSTGRES_PASSWORD env var has nothing to consume it.
Two footguns this creates:
dsn set without a password + passwordSecretRef set → the secret is silently ignored; the controller connects with no password and crashloops on a Postgres password authentication failed error that points at the DB, not at the contradictory Helm values.
dsn set with an inline password + passwordSecretRef set → works (DSN wins), but the mounted secret is dead weight and the password lands in the ConfigMap in plaintext.
Note — "both set" is sometimes valid: the secure DSN pattern embeds a {{ env "APIP_GW_CONTROLLER_STORAGE_POSTGRES_PASSWORD" }} token inside the dsn, which does consume passwordSecretRef at load time and keeps the password out of the ConfigMap. Any guard must allow this.
Proposed fix
- Guarded
fail: in gateway-config.yaml, for both the postgres and sqlserver/database blocks, fail at template render time when dsn is set and passwordSecretRef.name is set and the dsn does not reference the password env token — with a message directing the operator to either embed the {{ env … }} token in the DSN or drop passwordSecretRef. Consistent with the chart's existing fail/required validation (removed sqlserver key, missing host/db/user, encrypt enum).
- Docs: correct the misleading
values.yaml comments in the postgres/database blocks, which currently state both "Full DSN takes precedence over individual fields when set" and "Password is injected separately via … passwordSecretRef" — together implying a password-less DSN plus a separate secret works, which it does not.
Version
No response
Related Issue
No response
Description
The
gateway-helm-chartlets an operator configure the controller's external database (postgres/sqlserver) either via a fulldsnor via individualhost/port/database/userfields with the password injected separately from a Secret (passwordSecretRef). These two modes are mutually exclusive, but the chart neither enforces nor clearly documents that — leading to silent misconfiguration.Root cause in the controller:
buildPostgresDSN(gateway/gateway-controller/pkg/storage/postgres.go:140) andbuildSQLServerDSN(pkg/storage/sqlserver.go) return thedsnas-is when it is non-empty and never merge the separately-configuredPassword. The password field is only used whendsnis empty. At the chart level,gateway-config.yamlrenders thepassword = '{{ env … }}'line only in the non-DSN branch, so whendsnis set the injectedAPIP_GW_CONTROLLER_STORAGE_POSTGRES_PASSWORDenv var has nothing to consume it.Two footguns this creates:
dsnset without a password +passwordSecretRefset → the secret is silently ignored; the controller connects with no password and crashloops on a Postgrespassword authentication failederror that points at the DB, not at the contradictory Helm values.dsnset with an inline password +passwordSecretRefset → works (DSN wins), but the mounted secret is dead weight and the password lands in the ConfigMap in plaintext.Note — "both set" is sometimes valid: the secure DSN pattern embeds a
{{ env "APIP_GW_CONTROLLER_STORAGE_POSTGRES_PASSWORD" }}token inside thedsn, which does consumepasswordSecretRefat load time and keeps the password out of the ConfigMap. Any guard must allow this.Proposed fix
fail: ingateway-config.yaml, for both thepostgresandsqlserver/databaseblocks,failat template render time whendsnis set andpasswordSecretRef.nameis set and thedsndoes not reference the password env token — with a message directing the operator to either embed the{{ env … }}token in the DSN or droppasswordSecretRef. Consistent with the chart's existingfail/requiredvalidation (removedsqlserverkey, missing host/db/user,encryptenum).values.yamlcomments in thepostgres/databaseblocks, which currently state both "Full DSN takes precedence over individual fields when set" and "Password is injected separately via … passwordSecretRef" — together implying a password-less DSN plus a separate secret works, which it does not.Version
No response
Related Issue
No response