Skip to content

Commit 3cd5af5

Browse files
leonardocearmrujsilvelagbartolinimnencia
authored
feat: SCRAM-SHA-256 encode role passwords operator-side (#10724)
Before emitting `CREATE`/`ALTER ROLE ... PASSWORD '...'`, the operator now SCRAM-SHA-256 encodes any cleartext password operator-side (client-side from PostgreSQL's point of view). The literal PostgreSQL parses (and that extensions such as `pg_stat_statements` or `pgaudit` may capture) is the SCRAM verifier ultimately stored in `pg_authid.rolpassword`, never the cleartext secret. This matches what `psql \password` and libpq's `PQencryptPasswordConn` do, and applies to every basic-auth Secret the operator consumes: the `postgres` superuser, the application user, and managed-role password secrets. The existing statement-log suppression for CREATE/ALTER ROLE remains in effect. Passwords already supplied to PostgreSQL in its MD5 or SCRAM-SHA-256 shadow form are forwarded unchanged, so users who store a pre-hashed value in the Secret retain full control over the stored hash. Opt-out: set the annotation `cnpg.io/passwordPassthrough: "enabled"` on the basic-auth Secret to have the operator forward the password literal verbatim and let PostgreSQL encode it according to its own `password_encryption` GUC. The opt-out is per-Secret, so a single cluster can mix passthrough and operator-encoded secrets freely, restoring the pre-change behaviour for clusters that explicitly run with `password_encryption = md5` or otherwise need PostgreSQL to choose the hash format. Signed-off-by: Leonardo Cecchi <[email protected]> Signed-off-by: Armando Ruocco <[email protected]> Signed-off-by: Gabriele Bartolini <[email protected]> Signed-off-by: Marco Nenciarini <[email protected]> Co-authored-by: Armando Ruocco <[email protected]> Co-authored-by: Jaime Silvela <[email protected]> Co-authored-by: Gabriele Bartolini <[email protected]> Co-authored-by: Marco Nenciarini <[email protected]>
1 parent 1854d20 commit 3cd5af5

21 files changed

Lines changed: 727 additions & 75 deletions

‎.wordlist-en-custom.txt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ le
10621062
leonardoce
10631063
li
10641064
libpq
1065+
libpq's
10651066
lifecycle
10661067
lifecycles
10671068
linodeobjects
@@ -1183,6 +1184,7 @@ ownerReference
11831184
parseable
11841185
paru
11851186
passfile
1187+
passthrough
11861188
passwd
11871189
passwordSecret
11881190
passwordStatus
@@ -1602,6 +1604,7 @@ validUntil
16021604
validatingwebhookconfigurations
16031605
validator
16041606
valueFrom
1607+
verifier
16051608
virtualized
16061609
virtualxid
16071610
volumeMode

‎docs/src/declarative_role_management.md‎

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,23 +179,74 @@ stringData:
179179
password: SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
180180
```
181181

182+
:::warning
183+
The example above uses `stringData:`, where Kubernetes encodes the value
184+
for you, which is the safest path for pre-hashed passwords. If you must
185+
use `data:`, encode the bytes exactly with `printf '%s' "$hash" | base64`
186+
(or `echo -n "$hash" | base64`). A trailing newline from a naive
187+
`echo "$hash" | base64` makes the value miss the SCRAM/MD5 shadow-format
188+
check, so the operator falls back to treating it as cleartext and
189+
re-hashes it, and login stops working.
190+
:::
191+
182192
### Safety when transmitting cleartext passwords
183193

184-
While role passwords are safely managed in Kubernetes using Secrets,
185-
there is still a risk on the PostgreSQL side. If creating/altering a role with
186-
password, PostgreSQL may print the password as part of the query statement
187-
in some `postgres` logs, as mentioned in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createrole.html):
194+
Role passwords are safely managed in Kubernetes using Secrets, but the
195+
SQL path between the operator and PostgreSQL is also a concern. As noted
196+
in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createrole.html):
188197

189198
> The password will be transmitted to the server in cleartext, and it might
190199
> also be logged in the client's command history or the server log
191200

192-
CloudNativePG adds a safety layer by temporarily suppressing both statement
193-
logging (`log_statement`) and error statement logging
194-
(`log_min_error_statement`) for any CREATE or ALTER operation on a role with
195-
password, thus preventing leakage in both success and failure scenarios.
201+
CloudNativePG protects this path in two complementary ways:
202+
203+
1. Before emitting `CREATE`/`ALTER ROLE ... PASSWORD '...'`, the operator
204+
SCRAM-SHA-256 encodes any cleartext password operator-side (client-side
205+
from PostgreSQL's point of view). This is the standard PostgreSQL
206+
practice for keeping cleartext out of server logs and extensions like
207+
`pg_stat_statements` or `pgaudit`, and is the same encoding that
208+
`psql \password` and libpq's `PQencryptPasswordConn` perform. The
209+
literal PostgreSQL receives is the SCRAM-SHA-256 verifier stored in
210+
`pg_authid.rolpassword`. Passwords already provided in MD5 or
211+
SCRAM-SHA-256 shadow form are forwarded unchanged.
212+
2. The same `CREATE`/`ALTER ROLE` statements are executed inside a
213+
transaction that temporarily suppresses both statement logging
214+
(`log_statement`) and error statement logging
215+
(`log_min_error_statement`), preventing leakage to the PostgreSQL log
216+
in both success and failure scenarios.
217+
196218
The Status section of the cluster does not print the query statement for any
197219
managed role operation.
198220

221+
#### Opting out of operator-side encoding
222+
223+
If you need PostgreSQL (not the operator) to decide how the password is
224+
hashed (for example, on a cluster running `password_encryption = md5`),
225+
set the annotation `cnpg.io/passwordPassthrough: "enabled"` on the
226+
basic-auth Secret. The operator will then forward the password value
227+
verbatim.
228+
229+
:::warning
230+
The `cnpg.io/passwordPassthrough` annotation must be set on the
231+
**basic-auth Secret** itself, not on the `Cluster` resource. Placing it
232+
on the `Cluster` has no effect, and the operator will continue to apply
233+
SCRAM-SHA-256 encoding to the password before sending it to PostgreSQL.
234+
:::
235+
236+
The opt-in is per-Secret and applies to every basic-auth Secret the
237+
operator consumes (managed-role secrets, but also the superuser and
238+
application-user secrets), so a single cluster can mix passthrough
239+
secrets and operator-encoded secrets freely. The statement-logging
240+
suppression layer described above still applies in both modes.
241+
242+
:::warning
243+
With `cnpg.io/passwordPassthrough: "enabled"`, the operator forwards
244+
the Secret's `password` value verbatim. If that value is cleartext (the
245+
common case on a `password_encryption = md5` cluster), extensions such
246+
as `pg_stat_statements` or `pgaudit` will observe it. This is the
247+
expected trade-off for letting PostgreSQL choose the hash format.
248+
:::
249+
199250
## Unrealizable role configurations
200251

201252
In PostgreSQL, in some cases, commands cannot be honored by the database and

‎docs/src/installation_upgrade.md‎

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,66 @@ removed before installing the new one. This won't affect user data but
267267
only the operator itself.
268268

269269

270+
<!--
271+
### Upgrading to 1.30.0 or 1.29.2
272+
273+
:::info[Important]
274+
We strongly recommend that all CloudNativePG users upgrade to version
275+
1.30.0, or at least to the latest stable version of your current minor release
276+
(e.g., 1.29.2).
277+
:::
278+
279+
Starting from versions 1.30.0 and 1.29.2, for security reasons,
280+
CloudNativePG SCRAM-SHA-256 encodes role passwords **operator-side**
281+
(client-side from PostgreSQL's point of view) before issuing
282+
`CREATE`/`ALTER ROLE` statements. As a result, the literal that reaches
283+
the PostgreSQL parser (and that extensions such as `pg_stat_statements`
284+
or `pgaudit` may observe) is the same hash that ends up in
285+
`pg_authid.rolpassword`, never the cleartext secret. The encoding is
286+
applied to every basic-auth `Secret` the operator consumes: the
287+
`postgres` superuser secret, the application-user secret, and any
288+
managed-role password secret. Passwords already supplied in MD5 or
289+
SCRAM-SHA-256 shadow form are passed through unchanged.
290+
291+
Since PostgreSQL [14](https://www.postgresql.org/docs/release/14.0/),
292+
`password_encryption` defaults to `scram-sha-256`, so we do not expect
293+
existing installations to be affected by this change.
294+
295+
If your cluster has explicitly overridden `password_encryption` to a
296+
value other than `scram-sha-256` (for example, `md5`) and you want
297+
PostgreSQL (not the operator) to decide how the password is hashed,
298+
opt out by setting the annotation `cnpg.io/passwordPassthrough: "enabled"`
299+
on each basic-auth `Secret` the operator consumes. The operator will
300+
then forward the password value verbatim, and PostgreSQL will encode it
301+
according to its own `password_encryption` GUC.
302+
303+
:::warning
304+
The `cnpg.io/passwordPassthrough` annotation must be set on the
305+
**basic-auth Secret** itself, not on the `Cluster` resource. Placing it
306+
on the `Cluster` has no effect, and the operator will continue to apply
307+
SCRAM-SHA-256 encoding to the password before sending it to PostgreSQL.
308+
:::
309+
310+
:::warning
311+
With `cnpg.io/passwordPassthrough: "enabled"` the operator forwards the
312+
Secret's `password` value verbatim. If that value is cleartext, as is
313+
common on `password_encryption = md5` clusters, extensions such as
314+
`pg_stat_statements` or `pgaudit` will observe it.
315+
:::
316+
317+
See ["Opting out of operator-side encoding"](declarative_role_management.md#opting-out-of-operator-side-encoding)
318+
for details.
319+
320+
-->
321+
270322
### Upgrading to 1.29.1 or 1.28.3
271323

324+
:::info[Important]
325+
We strongly recommend that all CloudNativePG users upgrade to version
326+
1.29.1, or at least to the latest stable version of your current minor release
327+
(e.g., 1.28.x).
328+
:::
329+
272330
Version 1.29.1 and 1.28.3 ship the fix for `CVE-2026-44477` /
273331
`GHSA-423p-g724-fr39`. The metrics exporter now authenticates as a
274332
dedicated `cnpg_metrics_exporter` role with `pg_monitor` privileges
@@ -283,14 +341,6 @@ the metrics exporter
283341
role"](monitoring.md#manually-creating-the-metrics-exporter-role) in
284342
the monitoring documentation.
285343

286-
### Upgrading to 1.29.0 or 1.28.x
287-
288-
:::info[Important]
289-
We strongly recommend that all CloudNativePG users upgrade to version
290-
1.29.0, or at least to the latest stable version of your current minor release
291-
(e.g., 1.28.x).
292-
:::
293-
294344
### Upgrading to 1.27 from a previous minor version
295345

296346
Version 1.27 introduces a change in the default behavior of the

‎docs/src/labels_annotations.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ CloudNativePG manages the following predefined annotations:
201201
`cnpg.io/operatorVersion`
202202
: Version of the operator.
203203

204+
`cnpg.io/passwordPassthrough`
205+
: When set to `enabled` on a basic-auth `Secret` consumed by the
206+
operator (superuser, application user, or a managed-role password
207+
secret), the operator forwards the password value verbatim in the
208+
`CREATE`/`ALTER ROLE` statement instead of SCRAM-SHA-256 encoding
209+
it operator-side. PostgreSQL then encodes the value according to its
210+
own `password_encryption` setting. See [Opting out of operator-side encoding](declarative_role_management.md#opting-out-of-operator-side-encoding).
211+
204212
`cnpg.io/pgControldata`
205213
: Output of the `pg_controldata` command. This annotation replaces the old,
206214
deprecated `cnpg.io/hibernatePgControlData` annotation.

‎go.mod‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/cheynewallace/tabby v1.1.1
1212
github.com/cloudnative-pg/barman-cloud v0.5.1
1313
github.com/cloudnative-pg/cnpg-i v0.5.0
14-
github.com/cloudnative-pg/machinery v0.4.0
14+
github.com/cloudnative-pg/machinery v0.5.0
1515
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
1616
github.com/evanphx/json-patch/v5 v5.9.11
1717
github.com/go-logr/logr v1.4.3
@@ -103,6 +103,9 @@ require (
103103
github.com/prometheus/procfs v0.19.2 // indirect
104104
github.com/spf13/pflag v1.0.10 // indirect
105105
github.com/x448/float16 v0.8.4 // indirect
106+
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
107+
github.com/xdg-go/scram v1.2.0 // indirect
108+
github.com/xdg-go/stringprep v1.0.4 // indirect
106109
github.com/xlab/treeprint v1.2.0 // indirect
107110
go.yaml.in/yaml/v2 v2.4.4 // indirect
108111
golang.org/x/mod v0.35.0 // indirect

‎go.sum‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ github.com/cloudnative-pg/barman-cloud v0.5.1 h1:vjkXrrxo2DQXHT9u9usqhtaHiPZ/lTf
2424
github.com/cloudnative-pg/barman-cloud v0.5.1/go.mod h1:XPc5IUFP1y4cZX1sg+Pd8j9V4tmUEVnv3BGCpfQOOg8=
2525
github.com/cloudnative-pg/cnpg-i v0.5.0 h1:/TOzpNT6cwNgrpftTtrnLKdoHgMwd+88vZgXjlVgXeE=
2626
github.com/cloudnative-pg/cnpg-i v0.5.0/go.mod h1:7Gh4+UzhBpGhr4DreB1GN9wGYfvxwXCXZUyVt3zE/3I=
27-
github.com/cloudnative-pg/machinery v0.4.0 h1:3sfqrBptH4QQSVB4g10Z+7aiQRnh4g+6AsqsK0ibKaQ=
28-
github.com/cloudnative-pg/machinery v0.4.0/go.mod h1:OIwaTYAnLv8PmBmBvEf0BvMK2JBX6J+naTMg9UgV1FQ=
27+
github.com/cloudnative-pg/machinery v0.5.0 h1:hhTnkzn+AiN3NmbjCQ6RXj5rfqV3K6arzq6kdXAzcnQ=
28+
github.com/cloudnative-pg/machinery v0.5.0/go.mod h1:uuFjqBUjWn0a9uvAk1ixTSzPM0PrjaS+QiKLOIBqLm4=
2929
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
3030
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
3131
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -232,8 +232,15 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
232232
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
233233
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
234234
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
235+
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
236+
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
237+
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
238+
github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8=
239+
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
240+
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
235241
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
236242
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
243+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
237244
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
238245
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
239246
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
@@ -258,25 +265,48 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
258265
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
259266
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
260267
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
268+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
269+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
270+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
261271
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
262272
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
273+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
274+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
275+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
263276
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
264277
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
265278
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
266279
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
280+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
281+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
267282
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
268283
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
284+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
285+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
286+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
269287
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
288+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
289+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
270290
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
271291
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
292+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
293+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
272294
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
273295
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
296+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
297+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
298+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
299+
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
274300
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
275301
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
276302
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
277303
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
304+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
305+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
306+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
278307
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
279308
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
309+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
280310
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
281311
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
282312
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=

‎internal/management/controller/instance_controller.go‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import (
6262
"github.com/cloudnative-pg/cloudnative-pg/pkg/reconciler/replicaclusterswitch/conditions"
6363
clusterstatus "github.com/cloudnative-pg/cloudnative-pg/pkg/resources/status"
6464
"github.com/cloudnative-pg/cloudnative-pg/pkg/system"
65+
cnpgutils "github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
6566
)
6667

6768
const (
@@ -1353,7 +1354,13 @@ func (r *InstanceReconciler) reconcileUser(ctx context.Context, username string,
13531354
return fmt.Errorf("wrong username '%v' in secret, expected '%v'", usernameFromSecret, username)
13541355
}
13551356

1356-
err = postgresutils.SetUserPassword(ctx, username, password, db)
1357+
err = postgresutils.SetUserPassword(
1358+
ctx,
1359+
username,
1360+
password,
1361+
cnpgutils.IsPasswordPassthroughEnabled(&secret.ObjectMeta),
1362+
db,
1363+
)
13571364
if err != nil {
13581365
return err
13591366
}

‎internal/management/controller/roles/contract.go‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ type DatabaseRole struct {
4747
ValidUntil pgtype.Timestamp `json:"validUntil,omitempty"`
4848
InRoles []string `json:"inRoles,omitempty"`
4949
password sql.NullString `json:"-"`
50-
transactionID int64 `json:"-"`
50+
// passwordPassthrough, when true, instructs the instance manager to send the
51+
// password literal verbatim rather than SCRAM-SHA-256 encoding it
52+
// client-side. It is populated from the cnpg.io/passwordPassthrough
53+
// annotation on the Secret backing the role. Write-only: List() results
54+
// always carry false, since PostgreSQL has no concept of the annotation.
55+
passwordPassthrough bool `json:"-"`
56+
transactionID int64 `json:"-"`
5157
}
5258

5359
// passwordNeedsUpdating evaluates whether a DatabaseRole needs to be updated

0 commit comments

Comments
 (0)