Harden authentication, tenant isolation and security boundaries
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const password = process.env.APP_DATABASE_PASSWORD;
|
||||
if (!password || password.length < 24 || password.length > 256) {
|
||||
throw new Error('Set APP_DATABASE_PASSWORD to a dedicated password of 24–256 characters.');
|
||||
}
|
||||
const prisma = new PrismaClient();
|
||||
async function main() {
|
||||
const existing = await prisma.$queryRaw`SELECT 1 FROM pg_roles WHERE rolname = 'kita_runtime'`;
|
||||
if (!existing.length) await prisma.$executeRawUnsafe('CREATE ROLE kita_runtime LOGIN');
|
||||
const owned = await prisma.$queryRaw`SELECT 1 FROM pg_class c JOIN pg_roles r ON c.relowner = r.oid WHERE r.rolname = 'kita_runtime'
|
||||
UNION ALL SELECT 1 FROM pg_namespace n JOIN pg_roles r ON n.nspowner = r.oid WHERE r.rolname = 'kita_runtime'`;
|
||||
if (owned.length) throw new Error('Runtime role must not own tables or schemas.');
|
||||
const memberships = await prisma.$queryRaw`SELECT quote_ident(r.rolname) AS role FROM pg_auth_members m JOIN pg_roles r ON m.roleid = r.oid
|
||||
JOIN pg_roles member ON m.member = member.oid WHERE member.rolname = 'kita_runtime'`;
|
||||
for (const membership of memberships) await prisma.$executeRawUnsafe(`REVOKE ${membership.role} FROM kita_runtime`);
|
||||
// PostgreSQL quotes the secret. Only this server-produced SQL is executed.
|
||||
const [quoted] = await prisma.$queryRaw`SELECT format('ALTER ROLE kita_runtime PASSWORD %L LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOBYPASSRLS NOREPLICATION', ${password}) AS statement`;
|
||||
await prisma.$executeRawUnsafe(quoted.statement);
|
||||
for (const statement of [
|
||||
'REVOKE CREATE ON SCHEMA public FROM PUBLIC',
|
||||
'GRANT USAGE ON SCHEMA public TO kita_runtime',
|
||||
'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO kita_runtime',
|
||||
'GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO kita_runtime',
|
||||
'REVOKE ALL ON TABLE _prisma_migrations FROM kita_runtime',
|
||||
'REVOKE UPDATE, DELETE, TRUNCATE ON TABLE audit_logs FROM kita_runtime',
|
||||
]) await prisma.$executeRawUnsafe(statement);
|
||||
console.log('Runtime database grants configured. Re-run after future migrations.');
|
||||
}
|
||||
main().finally(() => prisma.$disconnect()).catch(error => {
|
||||
// Avoid putting a statement containing credentials into deployment logs.
|
||||
console.error('Runtime role provisioning failed:', error?.code ?? error?.name ?? 'unknown');
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user