Decision Tree
Need access control? → Define ROLE hierarchy
Need row isolation? → Enable RLS with policies
Need sensitive data? → Encrypt with pgcrypto
Need audit compliance? → Create AUDIT_LOG table
Need secure connections? → Enforce SSL/TLS
Database Security & RBAC Standards
Security must be implemented at the database layer (Defense in Depth), ensuring that even if the application layer is compromised, the data remains protected by strict access controls.
1. Role-Based Access Control (RBAC)
1.1 Standard Roles
Implement a hierarchy of roles to categorize users. Avoid assigning permissions to individual users; assign them to Roles.
ROLE_ADMIN: Full DDL/DML access. Capable of altering schema.
ROLE_APP_BACKEND: The role used by the API. Can SELECT, INSERT, UPDATE, DELETE on operational tables but cannot alter schema.
ROLE_READ_ONLY: For reporting/analytics tools. SELECT only.
ROLE_GUEST / ROLE_ANON: For unauthenticated public access (if applicable).
1.2 Granting Permissions
- Least Privilege: Start with no permissions. Grant only what is absolutely necessary.
- Grant Statements:
GRANT SELECT, INSERT, UPDATE ON TABLE users TO ROLE_APP_BACKEND;
GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO ROLE_APP_BACKEND;
- Revoke: Explicitly
REVOKE ALL from PUBLIC on sensitive tables to prevent accidental default access.
2. Row Level Security (RLS)
Use RLS to strictly enforce data isolation at the row level based on the current user context.
2.1 Implementing RLS
- Enable RLS:
ALTER TABLE sensitive_documents ENABLE ROW LEVEL SECURITY;
- Create Policy:
CREATE POLICY user_access_policy ON sensitive_documents
FOR ALL
USING (owner_id = current_setting('app.current_user_id')::INT);
2.2 Application Context
Ensure the application sets the context variable (e.g., app.current_user_id) at the start of every transaction to allow RLS to function correctly.
3. Data Protection
3.1 Sensitive Data
- Passwords: NEVER store plain-text passwords. Use
bcrypt or argon2 hashes.
- PII: Identify Personally Identifiable Information (Emails, Phones, IDs).
- Consider separate schemas or tables for PII with stricter access controls.
- Encrypt highly sensitive columns (e.g., Credit Card tokens) at rest if the database supports it (e.g.,
pgcrypto).
3.2 SQL Injection Prevention
- Prepared Statements: ALL application code must use Parameterized Queries/Prepared Statements.
- Dynamic SQL: In PL/pgSQL, use
EXECUTE ... USING ... to safely bind parameters in dynamic strings. Avoid simple string concatenation.
4. Audit & Compliance
4.1 Audit Logging Tables
Track sensitive operations for compliance (GDPR, SOC2, etc.).
- Log: WHO changed WHAT, WHEN, and the OLD/NEW values.
- Store in a separate
audit schema with restricted access.
4.2 Immutable Logs
- Make audit tables append-only: revoke
UPDATE and DELETE from all application roles.
- Consider log shipping or write-ahead log archiving for tamper-proofing.
5. Connection Security
5.1 Connection Pooling
- Application connections should use a pool (e.g., PgBouncer).
- Each pool should connect using the
ROLE_APP_BACKEND role, not a superuser.
5.2 SSL/TLS
- Enforce encrypted connections:
sslmode=require or verify-full.
- Ensure certificates are properly managed and rotated.
1---2name: security-rbac3description: Database Security, RBAC, and Access Control policies Trigger: When implementing role-based access control.4license: Apache-2.05---67## Decision Tree89```10Need access control? → Define ROLE hierarchy11Need row isolation? → Enable RLS with policies12Need sensitive data? → Encrypt with pgcrypto13Need audit compliance? → Create AUDIT_LOG table14Need secure connections? → Enforce SSL/TLS15```1617---1819# Database Security & RBAC Standards2021Security must be implemented at the database layer (Defense in Depth), ensuring that even if the application layer is compromised, the data remains protected by strict access controls.2223## 1. Role-Based Access Control (RBAC)2425### 1.1 Standard Roles2627Implement a hierarchy of roles to categorize users. Avoid assigning permissions to individual users; assign them to Roles.2829- **`ROLE_ADMIN`:** Full DDL/DML access. Capable of altering schema.30- **`ROLE_APP_BACKEND`:** The role used by the API. Can `SELECT`, `INSERT`, `UPDATE`, `DELETE` on operational tables but cannot alter schema.31- **`ROLE_READ_ONLY`:** For reporting/analytics tools. `SELECT` only.32- **`ROLE_GUEST` / `ROLE_ANON`:** For unauthenticated public access (if applicable).3334### 1.2 Granting Permissions3536- **Least Privilege:** Start with **no** permissions. Grant only what is absolutely necessary.37- **Grant Statements:**38 ```sql39 GRANT SELECT, INSERT, UPDATE ON TABLE users TO ROLE_APP_BACKEND;40 GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO ROLE_APP_BACKEND;41 ```42- **Revoke:** Explicitly `REVOKE ALL` from `PUBLIC` on sensitive tables to prevent accidental default access.4344## 2. Row Level Security (RLS)4546Use RLS to strictly enforce data isolation at the row level based on the current user context.4748### 2.1 Implementing RLS49501. **Enable RLS:**51 ```sql52 ALTER TABLE sensitive_documents ENABLE ROW LEVEL SECURITY;53 ```542. **Create Policy:**55 ```sql56 CREATE POLICY user_access_policy ON sensitive_documents57 FOR ALL58 USING (owner_id = current_setting('app.current_user_id')::INT);59 ```6061### 2.2 Application Context6263Ensure the application sets the context variable (e.g., `app.current_user_id`) at the start of every transaction to allow RLS to function correctly.6465## 3. Data Protection6667### 3.1 Sensitive Data6869- **Passwords:** NEVER store plain-text passwords. Use `bcrypt` or `argon2` hashes.70- **PII:** Identify Personally Identifiable Information (Emails, Phones, IDs).71 - Consider separate schemas or tables for PII with stricter access controls.72 - Encrypt highly sensitive columns (e.g., Credit Card tokens) at rest if the database supports it (e.g., `pgcrypto`).7374### 3.2 SQL Injection Prevention7576- **Prepared Statements:** ALL application code must use Parameterized Queries/Prepared Statements.77- **Dynamic SQL:** In PL/pgSQL, use `EXECUTE ... USING ...` to safely bind parameters in dynamic strings. Avoid simple string concatenation.7879## 4. Audit & Compliance8081### 4.1 Audit Logging Tables8283Track sensitive operations for compliance (GDPR, SOC2, etc.).8485- Log: WHO changed WHAT, WHEN, and the OLD/NEW values.86- Store in a separate `audit` schema with restricted access.8788### 4.2 Immutable Logs8990- Make audit tables append-only: revoke `UPDATE` and `DELETE` from all application roles.91- Consider log shipping or write-ahead log archiving for tamper-proofing.9293## 5. Connection Security9495### 5.1 Connection Pooling9697- Application connections should use a pool (e.g., PgBouncer).98- Each pool should connect using the `ROLE_APP_BACKEND` role, not a superuser.99100### 5.2 SSL/TLS101102- Enforce encrypted connections: `sslmode=require` or `verify-full`.103- Ensure certificates are properly managed and rotated.