mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-08 21:14:56 +09:00
users[].password is gone from the chart, its schema and the API type. Every application-user password is generated into <release>-credentials and kept across reconciles by lookup, so an upgraded release keeps the password it already has and a password left in values is ignored. The init-job mounts that Secret and applies each password with ALTER ROLE and a psql variable, so no password is rendered into the init-script Secret that Helm keeps in release history. While bootstrap is enabled the Secret is marked credentials-pending, and NOTES say the generated passwords apply once the init-job runs. Names reach superuser SQL and the init-script shell, so render-time guards reject a username, database or extension name outside [-._a-zA-Z0-9] or past the length PostgreSQL silently truncates: 63 bytes for a role or extension, 54 for a database, whose <db>_readonly role would otherwise truncate and fail the next run. A username over 63 bytes that the credentials Secret already carries still upgrades. users.postgres, the CNPG superuser, is rejected in every bootstrap state. Changing a database's key in values drops the database, so the reject message and the README give the rename that keeps the data: a platform administrator renames it and its roles as the CNPG superuser before the key changes. The init-job cannot hang its Helm hook: the readiness wait ends on elapsed time below activeDeadlineSeconds and the Job never retries, so a purged restore target fails with a diagnostic. The delete-users pass reads managed users from pg_shdescription instead of parsing the version-dependent \du+ layout, which on PostgreSQL 16 and later matched nothing and left a removed user able to log in; it compares names as CREATE ROLE stores them and reassigns a removed user's objects in every database before dropping it. A database without roles renders, and extension names are quoted for hyphenated names and folded to lowercase so they resolve as they did unquoted. A value that carries its own surrounding quotes, the only way a hyphenated extension rendered before, has that pair removed and keeps its case, so such a release still upgrades. The README reads a password with jq, since jsonpath splits a dotted key. Signed-off-by: Alexey Artamonov <aleksei.artamonov@aenix.io>
88 lines
3.3 KiB
YAML
88 lines
3.3 KiB
YAML
suite: init-script removes users dropped from values
|
|
|
|
# The delete-users pass revokes a user that left .Values.users. Reading the managed
|
|
# users by parsing `\du+` and matching the description in column 4 breaks on
|
|
# PostgreSQL 16 and later, which dropped the "Member of" column, so the description
|
|
# sits in column 3 and nothing matches: a removed user keeps its LOGIN and old
|
|
# password. Query the catalog instead, as the database and role passes do.
|
|
|
|
templates:
|
|
- templates/init-script.yaml
|
|
|
|
release:
|
|
name: pg-test
|
|
namespace: tenant-test
|
|
|
|
set:
|
|
_cluster:
|
|
scheduling: {}
|
|
|
|
tests:
|
|
- it: reads the managed users from the catalog, not from the \du+ layout
|
|
set:
|
|
users:
|
|
app: {}
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-init-script
|
|
asserts:
|
|
- matchRegex:
|
|
path: stringData["init.sh"]
|
|
pattern: "MANAGED_USERS=\\$\\(psql -v ON_ERROR_STOP=1 -t -A -c \"SELECT r.rolname FROM pg_roles r JOIN pg_shdescription s ON s.objoid = r.oid AND s.classoid = 'pg_authid'::regclass WHERE s.description = 'user managed by helm'\"\\)"
|
|
- notMatchRegex:
|
|
path: stringData["init.sh"]
|
|
pattern: 'du\+'
|
|
|
|
# CREATE ROLE keeps only the first 63 bytes of a longer name, so the catalog holds
|
|
# a long user under its truncated name. Comparing it against the declared full
|
|
# name would call it undeclared and drop it on every run, so the declared names
|
|
# are compared truncated the same way.
|
|
- it: compares declared users truncated to 63 bytes
|
|
release:
|
|
name: pg-test
|
|
namespace: tenant-test
|
|
upgrade: true
|
|
kubernetesProvider:
|
|
scheme:
|
|
"v1/Secret":
|
|
gvr: {version: v1, resource: secrets}
|
|
namespaced: true
|
|
objects:
|
|
- apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: pg-test-credentials
|
|
namespace: tenant-test
|
|
data:
|
|
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu: ZXhpc3RpbmdwYXNzd29yZA==
|
|
set:
|
|
users:
|
|
app: {}
|
|
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu: {}
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-init-script
|
|
asserts:
|
|
- matchRegex:
|
|
path: stringData["init.sh"]
|
|
pattern: 'DEFINED_USERS="app uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu"'
|
|
|
|
# A removed user may own objects in any database, and REASSIGN OWNED / DROP OWNED
|
|
# act only on the database they run in; run in the postgres database alone, DROP
|
|
# USER then fails on the objects elsewhere and wedges every later init-job run.
|
|
# Run them in every connectable database before dropping the user.
|
|
- it: reassigns and drops a removed user's objects in every database
|
|
set:
|
|
users:
|
|
app: {}
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-init-script
|
|
asserts:
|
|
- matchRegex:
|
|
path: stringData["init.sh"]
|
|
pattern: "ALL_DBS=\\$\\(psql -v ON_ERROR_STOP=1 -t -A -c \"SELECT datname FROM pg_database WHERE datallowconn AND NOT datistemplate\"\\)"
|
|
- matchRegex:
|
|
path: stringData["init.sh"]
|
|
pattern: 'for db in \$ALL_DBS; do\npsql -v ON_ERROR_STOP=1 --echo-all --dbname "\$db" <<EOT\nREASSIGN OWNED BY "\$user" TO postgres;\nDROP OWNED BY "\$user";\nEOT\ndone\npsql -v ON_ERROR_STOP=1 --echo-all -c "DROP USER \\"\$user\\";"'
|