feat: implement tenant isolation with PostgreSQL RLS
- users + tenant_memberships tables (tenant-scoped)
- RLS policy on tenant_memberships using set_config('app.current_tenant_id', ...)
- withTenantContext() helper for transaction-scoped tenant context
- separate non-superuser app role (b2bcall_app): the default Docker postgres
user is SUPERUSER and always bypasses RLS even with FORCE, so the app must
never connect through the migration/owner role. Documented in
docs/TENANT_ISOLATION.md.
- automated isolation test proving tenant A never sees tenant B's data
This commit is contained in:
28
scripts/db-setup-app-role.sh
Executable file
28
scripts/db-setup-app-role.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sets/rotates the password of the restricted, non-superuser Postgres role
|
||||
# used by the running application (b2bcall_app). The role itself is created
|
||||
# by the "app_role_and_grants" Prisma migration; this script only sets the
|
||||
# secret, which must never be embedded in a committed migration file.
|
||||
#
|
||||
# Reads POSTGRES_USER/PASSWORD (superuser, to run the ALTER ROLE) and
|
||||
# POSTGRES_APP_USER/POSTGRES_APP_PASSWORD from .env.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source "$ROOT_DIR/.env"
|
||||
set +a
|
||||
|
||||
: "${POSTGRES_APP_USER:?POSTGRES_APP_USER not set in .env}"
|
||||
: "${POSTGRES_APP_PASSWORD:?POSTGRES_APP_PASSWORD not set in .env}"
|
||||
|
||||
docker exec -i b2bcall-postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" \
|
||||
-v ON_ERROR_STOP=1 \
|
||||
-v app_user="$POSTGRES_APP_USER" \
|
||||
-v app_password="$POSTGRES_APP_PASSWORD" \
|
||||
<<'SQL'
|
||||
ALTER ROLE :"app_user" WITH PASSWORD :'app_password';
|
||||
SQL
|
||||
|
||||
echo "Senha do role '${POSTGRES_APP_USER}' aplicada."
|
||||
Reference in New Issue
Block a user