Files
dtf-system/local/bootstrap.py
Cauê Faleiros 9d348ca893
All checks were successful
Build and deploy / Validate source (push) Successful in 7s
Build and deploy / Publish images and notify Portainer (push) Successful in 49s
fix: support arbitrary production database passwords
2026-09-18 12:18:43 -03:00

38 lines
1.9 KiB
Python

"""One-shot schema/role setup. Only this job receives database admin credentials."""
import os
from pathlib import Path
import psycopg
from psycopg import sql
def admin_connect():
if os.environ.get('DATABASE_ADMIN_HOST'):
return psycopg.connect(
host=os.environ['DATABASE_ADMIN_HOST'],
dbname=os.environ['DATABASE_ADMIN_NAME'],
user=os.environ['DATABASE_ADMIN_USER'],
password=os.environ['DATABASE_ADMIN_PASSWORD'],
)
return psycopg.connect(os.environ['DATABASE_ADMIN_URL'])
def main():
role = os.environ['APP_DB_USER']
with admin_connect() as c:
admin, database = c.execute('SELECT current_user,current_database()').fetchone()
if role == admin:
raise RuntimeError('Application and database administrator must differ')
if not c.execute('SELECT 1 FROM pg_roles WHERE rolname=%s', (role,)).fetchone():
c.execute(sql.SQL('CREATE ROLE {} LOGIN').format(sql.Identifier(role)))
c.execute(sql.SQL('ALTER ROLE {} NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS PASSWORD {}').format(
sql.Identifier(role), sql.Literal(os.environ['APP_DB_PASSWORD'])))
c.execute(Path(__file__).with_name('schema.sql').read_text())
c.execute(sql.SQL('REVOKE CREATE ON SCHEMA public FROM PUBLIC'))
c.execute(sql.SQL('GRANT CONNECT ON DATABASE {} TO {}').format(sql.Identifier(database),sql.Identifier(role)))
c.execute(sql.SQL('GRANT USAGE ON SCHEMA dtf_local TO {}').format(sql.Identifier(role)))
c.execute(sql.SQL('GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA dtf_local TO {}').format(sql.Identifier(role)))
c.execute(sql.SQL('GRANT USAGE,SELECT ON ALL SEQUENCES IN SCHEMA dtf_local TO {}').format(sql.Identifier(role)))
print('Local schema migrated; runtime role has DML only.')
if __name__ == '__main__': main()