RBAC (api/internal/authz) is live on /query and /dashboards, backed by a new enterprise/ module (session issuance, audit logging, RBAC storage, OIDC/SAML protocol wiring) that core never imports -- only calls over HTTP. Found and fixed a real cross-tenant vulnerability in dashboards (no tenant_id filtering at all) while writing the threat model doc. Two things are explicitly NOT done, documented rather than hidden: tenant isolation for log data itself (/query still shares one ClickHouse connection and Tantivy index across every tenant -- RBAC controls who can query, not what a query can see), and human SSO login (protocol wiring exists, no HTTP handler calls it yet). See docs/security/threat-model.md and docs/phase-4-runbook.md. Also adds deploy/ (Go Operator + Helm chart, validated offline only -- no cluster was reachable in this environment).
50 lines
2.0 KiB
Bash
50 lines
2.0 KiB
Bash
#!/usr/bin/env bash
|
|
# Applies migrations/*.sql to Postgres in filename order, tracking what's
|
|
# already been applied in a schema_migrations table -- same shape as
|
|
# /storage/migrate.sh, adapted for psql instead of curl since Postgres
|
|
# supports real transactions per file (kept to one DDL object per file
|
|
# anyway, for repo-wide consistency of what a migration "version" means).
|
|
set -euo pipefail
|
|
|
|
POSTGRES_HOST="${POSTGRES_HOST:-localhost}"
|
|
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
|
POSTGRES_USER="${POSTGRES_USER:-sentry}"
|
|
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}"
|
|
POSTGRES_DATABASE="${POSTGRES_DATABASE:-sentry_metadata}"
|
|
# Password for the restricted audit-log-writer Postgres role (Phase 4
|
|
# task 4, see /docs/phase-4-isolation-design.md's audit logging
|
|
# section) -- a second, narrower-granted role, not the shared
|
|
# POSTGRES_PASSWORD above. Passed to psql via -v so the migration SQL
|
|
# file can reference it as :'audit_writer_password' without ever
|
|
# hardcoding a credential in a file checked into git.
|
|
AUDIT_WRITER_PASSWORD="${AUDIT_WRITER_PASSWORD:-audit-writer-dev-only}"
|
|
|
|
export PGPASSWORD="$POSTGRES_PASSWORD"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
MIGRATIONS_DIR="${SCRIPT_DIR}/migrations"
|
|
|
|
psql_exec() {
|
|
psql -v ON_ERROR_STOP=1 -X -q -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DATABASE" \
|
|
-v audit_writer_password="$AUDIT_WRITER_PASSWORD" "$@"
|
|
}
|
|
|
|
echo "Ensuring schema_migrations table exists..."
|
|
psql_exec -c "CREATE TABLE IF NOT EXISTS schema_migrations (version TEXT PRIMARY KEY, applied_at TIMESTAMPTZ NOT NULL DEFAULT now())"
|
|
|
|
applied="$(psql_exec -t -A -c "SELECT version FROM schema_migrations")"
|
|
|
|
shopt -s nullglob
|
|
for file in "${MIGRATIONS_DIR}"/*.sql; do
|
|
version="$(basename "$file")"
|
|
if grep -qx "$version" <<< "$applied"; then
|
|
echo "skip ${version} (already applied)"
|
|
continue
|
|
fi
|
|
echo "apply ${version}"
|
|
psql_exec -f "$file"
|
|
psql_exec -c "INSERT INTO schema_migrations (version) VALUES ('${version}')"
|
|
done
|
|
|
|
echo "Migrations complete."
|