mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-07-22 16:55:40 +02:00
PostgreSQL's log_min_error_statement defaults to 'error', so whenever a CREATE/ALTER ROLE ... PASSWORD statement errored, the full statement text -- including the plaintext password -- was written to /opt/so/log/postgres/postgres.log. The role-provisioning paths (init-db.sh for so_postgres, so-telegraf-postgres for per-minion telegraf roles) both dispatch such DDL, the latter on every state.apply. - init-db.sh / so-telegraf-postgres: SET log_min_error_statement = panic before the password-bearing DDL so an error no longer emits the STATEMENT line. The ERROR message itself (no password) still logs, preserving debuggability. - logrotate: add a postgres stanza (daily, keep 14, copytruncate, compress) so postgres.log is rotated like every other service and leaked content can't persist indefinitely. copytruncate is required because the container holds the log open via redirected stderr. - soup: scrub any already-logged PASSWORD lines from postgres.log during post_to_3.2.0, rewriting in place to preserve the inode postgres is writing to.
39 lines
2.1 KiB
Bash
39 lines
2.1 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
# Create or update application user for SOC platform access
|
|
# This script runs on first database initialization via docker-entrypoint-initdb.d
|
|
# The password is properly escaped to handle special characters
|
|
if [ -z "${SO_POSTGRES_PASS:-}" ] && [ -n "${SO_POSTGRES_PASS_FILE:-}" ] && [ -r "$SO_POSTGRES_PASS_FILE" ]; then
|
|
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.
|
|
SET log_min_error_statement = panic;
|
|
DO \$\$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${SO_POSTGRES_USER}') THEN
|
|
EXECUTE format('CREATE ROLE %I WITH LOGIN PASSWORD %L', '${SO_POSTGRES_USER}', '${SO_POSTGRES_PASS}');
|
|
ELSE
|
|
EXECUTE format('ALTER ROLE %I WITH PASSWORD %L', '${SO_POSTGRES_USER}', '${SO_POSTGRES_PASS}');
|
|
END IF;
|
|
END
|
|
\$\$;
|
|
GRANT ALL ON SCHEMA public TO "$SO_POSTGRES_USER";
|
|
GRANT ALL PRIVILEGES ON DATABASE "$POSTGRES_DB" TO "$SO_POSTGRES_USER";
|
|
-- Lock the SOC database down at the connect layer; PUBLIC gets CONNECT
|
|
-- by default, which would let per-minion telegraf roles open sessions
|
|
-- here. They have no schema/table grants inside so reads fail, but
|
|
-- revoking CONNECT closes the soft edge entirely.
|
|
REVOKE CONNECT ON DATABASE "$POSTGRES_DB" FROM PUBLIC;
|
|
GRANT CONNECT ON DATABASE "$POSTGRES_DB" TO "$SO_POSTGRES_USER";
|
|
EOSQL
|
|
|
|
# Bootstrap the Telegraf metrics database. Per-minion roles + schemas are
|
|
# reconciled on every state.apply by postgres/telegraf_users.sls; this block
|
|
# only ensures the shared database exists on first initialization.
|
|
if ! psql -U "$POSTGRES_USER" -tAc "SELECT 1 FROM pg_database WHERE datname='so_telegraf'" | grep -q 1; then
|
|
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE DATABASE so_telegraf"
|
|
fi |