←Back to Documentation
Role-Based Access Control
Fine-grained access control with roles, permissions, and row-level security
Overview
entropyDB RBAC features:
- • Roles: Group permissions into reusable roles
- • Privileges: Database, table, column, and row-level permissions
- • Row-Level Security: Filter data based on user context
- • Column Masking: Hide sensitive columns from users
- • Attribute-Based Access: Dynamic access policies
Roles and Permissions
-- Create roles CREATE ROLE readonly; CREATE ROLE developer; CREATE ROLE admin WITH ADMIN OPTION; -- Grant database privileges GRANT CONNECT ON DATABASE mydb TO readonly; GRANT CREATE ON DATABASE mydb TO developer; GRANT ALL PRIVILEGES ON DATABASE mydb TO admin; -- Grant table privileges GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO developer; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin; -- Grant column-specific privileges GRANT SELECT (id, name, email) ON users TO readonly; GRANT SELECT ON users TO developer; -- All columns GRANT UPDATE (status) ON users TO developer; -- Grant on specific objects GRANT EXECUTE ON FUNCTION calculate_balance TO developer; GRANT USAGE ON SEQUENCE user_id_seq TO developer; -- Assign roles to users GRANT readonly TO alice; GRANT developer TO bob; GRANT admin TO charlie; -- Role inheritance CREATE ROLE poweruser; GRANT readonly TO poweruser; GRANT poweruser TO alice; -- alice gets readonly privileges
Row-Level Security
-- Enable row-level security
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Create policy: Users see only their own orders
CREATE POLICY user_orders ON orders
FOR SELECT
USING (user_id = current_user_id());
-- Create policy: Managers see team orders
CREATE POLICY manager_orders ON orders
FOR SELECT
USING (
department_id IN (
SELECT department_id
FROM employees
WHERE user_id = current_user_id()
AND role = 'manager'
)
);
-- Create policy: Admins see everything
CREATE POLICY admin_all_orders ON orders
FOR ALL
USING (current_user_has_role('admin'));
-- Multiple policies with different operations
CREATE POLICY user_insert_own_orders ON orders
FOR INSERT
WITH CHECK (user_id = current_user_id());
CREATE POLICY user_update_own_orders ON orders
FOR UPDATE
USING (user_id = current_user_id())
WITH CHECK (user_id = current_user_id());
-- Disable RLS for specific role
ALTER TABLE orders FORCE ROW LEVEL SECURITY;
GRANT BYPASSRLS TO admin;
-- Check active policies
SELECT * FROM pg_policies WHERE tablename = 'orders';Column Masking
-- Create masking policy
CREATE MASKING POLICY mask_email AS (email TEXT)
RETURNS TEXT AS $$
SELECT CASE
WHEN current_user_has_role('admin') THEN email
WHEN current_user_has_role('support') THEN
SUBSTRING(email, 1, 3) || '***@' || SPLIT_PART(email, '@', 2)
ELSE '***@***.com'
END
$$ LANGUAGE SQL;
-- Apply masking policy
ALTER TABLE users
ALTER COLUMN email
SET MASKING POLICY mask_email;
-- Create policy for credit card numbers
CREATE MASKING POLICY mask_credit_card AS (cc_number TEXT)
RETURNS TEXT AS $$
SELECT CASE
WHEN current_user_has_role('finance') THEN cc_number
ELSE '****-****-****-' || RIGHT(cc_number, 4)
END
$$ LANGUAGE SQL;
ALTER TABLE payments
ALTER COLUMN credit_card
SET MASKING POLICY mask_credit_card;
-- Dynamic masking based on context
CREATE MASKING POLICY dynamic_salary AS (salary NUMERIC)
RETURNS NUMERIC AS $$
SELECT CASE
WHEN current_user_id() = employee_id THEN salary -- Own salary
WHEN current_user_has_role('hr') THEN salary -- HR sees all
WHEN current_user_is_manager_of(employee_id) THEN salary -- Manager sees team
ELSE NULL -- Others see nothing
END
$$ LANGUAGE SQL;Attribute-Based Access Control
-- Create attribute-based policy
CREATE POLICY regional_access ON customers
FOR SELECT
USING (
region = current_setting('app.user_region')
OR current_user_has_role('global_viewer')
);
-- Set user attributes in session
SET app.user_region = 'us-west';
SET app.user_department = 'sales';
SET app.user_clearance_level = '3';
-- Policy using multiple attributes
CREATE POLICY document_access ON documents
FOR SELECT
USING (
(classification_level <= current_setting('app.user_clearance_level')::int)
AND
(department = current_setting('app.user_department')
OR is_public = true)
);
-- Time-based access
CREATE POLICY business_hours_access ON sensitive_data
FOR SELECT
USING (
current_user_has_role('admin')
OR
(EXTRACT(HOUR FROM NOW()) BETWEEN 9 AND 17
AND EXTRACT(DOW FROM NOW()) BETWEEN 1 AND 5)
);
-- IP-based access
CREATE POLICY office_network_access ON confidential
FOR ALL
USING (
current_user_has_role('remote_admin')
OR
inet_client_addr() <<= '10.0.0.0/8'::inet
);Best Practices
Role Design
- • Follow principle of least privilege
- • Use role hierarchies for inheritance
- • Regular access reviews
- • Document role purposes
Security Policies
- • Test policies thoroughly
- • Monitor policy performance
- • Keep policies simple and maintainable
- • Use indexes on policy columns