diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index eb63a1d60..9f02eb32a 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -881,12 +881,7 @@ recollate_postgres() { } scrub_postgres_log_passwords() { - # Before 3.2 PostgreSQL could log the full CREATE/ALTER ROLE ... PASSWORD - # statement -- with the plaintext password -- to postgres.log whenever such a - # DDL errored, because log_min_error_statement defaulted to 'error'. The leak - # is fixed going forward (the provisioning scripts now SET log_min_error_statement - # = panic), but any already-logged secret persists in the on-disk log. Purge it - # here. Only the manager runs so-postgres, so this is a local scrub. + # Purge plaintext passwords a pre-3.2 postgres could log on DDL errors. local log=/opt/so/log/postgres/postgres.log [[ -f "$log" ]] || return 0 if ! grep -qai "PASSWORD '" "$log" 2>/dev/null; then @@ -896,9 +891,7 @@ scrub_postgres_log_passwords() { echo "Removing leaked password statements from $log." local tmp tmp=$(mktemp) - # Drop every line carrying a PASSWORD literal, then rewrite in place with - # `cat >` so the file keeps its inode -- postgres holds it open via redirected - # stderr and must keep logging to the same file. + # Rewrite in place (cat >) to keep the inode postgres is writing to. grep -avi "PASSWORD '" "$log" > "$tmp" 2>/dev/null || true cat "$tmp" > "$log" rm -f "$tmp" @@ -988,11 +981,7 @@ post_to_3.2.0() { # Recollate due to image OS rebase recollate_postgres - # The SOC database (so_postgres role, schema/db grants, so_telegraf) is - # bootstrapped idempotently by the postgres.enabled highstate that runs - # before this postupgrade step, so no explicit bootstrap call is needed here. - - # Purge any plaintext passwords a pre-3.2 postgres logged on DDL errors. + # SOC database bootstrap is handled by the postgres.enabled highstate. scrub_postgres_log_passwords # Generate 9.3.7 elastic agent installers diff --git a/salt/postgres/enabled.sls b/salt/postgres/enabled.sls index ad6ff7819..fa91d146a 100644 --- a/salt/postgres/enabled.sls +++ b/salt/postgres/enabled.sls @@ -92,12 +92,9 @@ postgres_wait_ready: - docker_container: so-postgres - file: postgres_sbin -# Re-run the SOC database bootstrap on every highstate so a cluster left -# partially initialized -- e.g. the container was restarted mid first-init by a -# watch trigger, so docker-entrypoint-initdb.d never completed -- self-heals: -# the so_postgres role, its schema/database grants, and the so_telegraf database -# are all reconciled idempotently. init-db.sh is idempotent and race-safe. -# POSTGRES_USER is injected because the container env intentionally omits it. +# Reconcile the SOC database (role, grants, so_telegraf) every highstate so a +# partially-initialized cluster self-heals. POSTGRES_USER is injected because +# the container env omits it. postgres_bootstrap_soc_db: cmd.run: - name: docker exec -u postgres -e POSTGRES_USER=postgres so-postgres bash /docker-entrypoint-initdb.d/init-db.sh diff --git a/salt/postgres/files/init-db.sh b/salt/postgres/files/init-db.sh index 540980469..4d65b0c97 100644 --- a/salt/postgres/files/init-db.sh +++ b/salt/postgres/files/init-db.sh @@ -8,16 +8,10 @@ if [ -z "${SO_POSTGRES_PASS:-}" ] && [ -n "${SO_POSTGRES_PASS_FILE:-}" ] && [ -r SO_POSTGRES_PASS="$(< "$SO_POSTGRES_PASS_FILE")" fi psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - -- Shield the plaintext password below from postgres.log if this DDL errors: - -- log_min_error_statement defaults to 'error', which would append a STATEMENT line - -- containing the full CREATE/ALTER ROLE ... PASSWORD text. panic suppresses that. + -- Keep the password out of postgres.log if this DDL errors. SET log_min_error_statement = panic; - -- Race-safe upsert: try CREATE, and if the role was created concurrently - -- (another session re-entering init) fall back to ALTER. Catching the - -- exception -- rather than an IF NOT EXISTS check -- avoids a TOCTOU window - -- where CREATE ROLE would abort the whole script with a duplicate-key error - -- and skip the grants below. Both SQLSTATEs are covered: duplicate_object - -- (role already exists) and unique_violation (racy pg_authid index insert). + -- Idempotent, race-safe upsert: CREATE, falling back to ALTER if the role + -- already exists or is created concurrently. DO \$\$ BEGIN BEGIN diff --git a/salt/postgres/telegraf_users.sls b/salt/postgres/telegraf_users.sls index 62c33b892..4c63d40b0 100644 --- a/salt/postgres/telegraf_users.sls +++ b/salt/postgres/telegraf_users.sls @@ -8,10 +8,8 @@ {% from 'vars/globals.map.jinja' import GLOBALS %} {% from 'telegraf/map.jinja' import TELEGRAFMERGED %} -{# postgres_wait_ready and the so-postgres container are declared in - postgres.enabled; include it so the require references below resolve and so - state.apply postgres.telegraf_users on its own (e.g. from orch.deploy_newnode) - still has those IDs in scope. Salt de-duplicates the circular include. #} +{# postgres.enabled declares the so-postgres container and postgres_wait_ready + that the requires below reference. Salt de-duplicates the circular include. #} include: - postgres.enabled diff --git a/salt/postgres/tools/sbin/so-telegraf-postgres b/salt/postgres/tools/sbin/so-telegraf-postgres index e6cc69fa6..17e4da744 100644 --- a/salt/postgres/tools/sbin/so-telegraf-postgres +++ b/salt/postgres/tools/sbin/so-telegraf-postgres @@ -71,9 +71,7 @@ EOSQL -v role_user="$ROLE_USER" \ -v role_pass="$ROLE_PASS" \ -U postgres -d so_telegraf <<'EOSQL' --- Shield the plaintext password below from postgres.log if this DDL errors: --- log_min_error_statement defaults to 'error', which would append a STATEMENT line --- containing the full CREATE/ALTER ROLE ... PASSWORD text. panic suppresses that. +-- Keep the password out of postgres.log if this DDL errors. SET log_min_error_statement = panic; SELECT format( CASE WHEN EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = :'role_user')