openvibers/openvibe.host Commits
Data role: service roles can no longer connect to the maintenance database. PostgreSQL lets PUBLIC connect to 'postgres' by default, so the end-to-end check on the host showed a service's runtime role reaching it (catalogs only). Connect is revoked from PUBLIC there and granted to the PgBouncer auth and monitoring roles alone; each service database already refused everyone but its own roles. The check also confirmed SCRAM through PgBouncer, DML-only runtime roles with a 15 s statement timeout, and Valkey users confined to their prefix without dangerous commands.
Changes
@@@ -132,6 +132,9 @@ REVOKE ALL ON FUNCTION pgbouncer.get_auth(TEXT) FROM PUBLIC;GRANT USAGE ON SCHEMA pgbouncer TO pgbouncer_auth;GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(TEXT) TO pgbouncer_auth;CREATE EXTENSION IF NOT EXISTS pg_stat_statements;++-- Service roles reach only their own database: nobody else connects to the maintenance database.++REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;++GRANT CONNECT ON DATABASE postgres TO pgbouncer_auth, ov_monitor;SQL# ── 6. PgBouncer (its auth user's password is the one plaintext it must hold: root and postgres only) ──@@@ -44,6 +44,7 @@ runTests([assert.match(p, /pgbackrest --stanza=openvibe archive-push %p/);assert.match(p, /repo1-cipher-type=aes-256-cbc/);assert.match(p, /repo1-path=\/openvibe-pgbackrest/, 'beside, never under, the pruned backup prefix');++ assert.match(p, /REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;/, 'service roles cannot reach the maintenance database');const lib = read('lib.sh');assert.match(lib, /SCRAM-SHA-256\$\{it\}/, 'passwords reach SQL as SCRAM secrets');// A secret may be hashed (sha256hex, scram) or written into a file by redirection; never printed to the output.
@@ -132,6 +132,9 @@ REVOKE ALL ON FUNCTION pgbouncer.get_auth(TEXT) FROM PUBLIC;
@@ -132,6 +132,9 @@ REVOKE ALL ON FUNCTION pgbouncer.get_auth(TEXT) FROM PUBLIC;
GRANT USAGE ON SCHEMA pgbouncer TO pgbouncer_auth;
GRANT USAGE ON SCHEMA pgbouncer TO pgbouncer_auth;
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(TEXT) TO pgbouncer_auth;
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(TEXT) TO pgbouncer_auth;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
+-- Service roles reach only their own database: nobody else connects to the maintenance database.
+REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;
+GRANT CONNECT ON DATABASE postgres TO pgbouncer_auth, ov_monitor;
SQL
SQL
# ── 6. PgBouncer (its auth user's password is the one plaintext it must hold: root and postgres only) ──
# ── 6. PgBouncer (its auth user's password is the one plaintext it must hold: root and postgres only) ──
@@ -44,6 +44,7 @@ runTests([
@@ -44,6 +44,7 @@ runTests([
assert.match(p, /pgbackrest --stanza=openvibe archive-push %p/);
assert.match(p, /pgbackrest --stanza=openvibe archive-push %p/);
assert.match(p, /repo1-cipher-type=aes-256-cbc/);
assert.match(p, /repo1-cipher-type=aes-256-cbc/);
assert.match(p, /repo1-path=\/openvibe-pgbackrest/, 'beside, never under, the pruned backup prefix');
assert.match(p, /repo1-path=\/openvibe-pgbackrest/, 'beside, never under, the pruned backup prefix');
+ assert.match(p, /REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;/, 'service roles cannot reach the maintenance database');
const lib = read('lib.sh');
const lib = read('lib.sh');
assert.match(lib, /SCRAM-SHA-256\$\{it\}/, 'passwords reach SQL as SCRAM secrets');
assert.match(lib, /SCRAM-SHA-256\$\{it\}/, 'passwords reach SQL as SCRAM secrets');
// A secret may be hashed (sha256hex, scram) or written into a file by redirection; never printed to the output.
// A secret may be hashed (sha256hex, scram) or written into a file by redirection; never printed to the output.