367 lines
15 KiB
Markdown
367 lines
15 KiB
Markdown
# c77_rbac Tutorial - Part 3: Implementing RBAC
|
|
|
|
**Tutorial Navigation:**
|
|
- [Part 1: Getting Started](TUTORIAL-Part1.md) - Prerequisites and installation
|
|
- [Part 2: Building the TechCorp Database](TUTORIAL-Part2.md) - Creating the schema and data
|
|
- **Part 3: Implementing RBAC** (this document) - Setting up roles and permissions
|
|
- [Part 4: Row-Level Security](TUTORIAL-Part4.md) - Applying access controls
|
|
- [Part 5: Testing and Validation](TUTORIAL-Part5.md) - Security testing
|
|
- [Part 6: Advanced Features](TUTORIAL-Part6.md) - Bulk operations and monitoring
|
|
|
|
---
|
|
|
|
## Chapter 3: Setting Up RBAC Roles and Features
|
|
|
|
Now we'll implement a comprehensive role-based access control system for our TechCorp database. This chapter covers defining features, creating roles, and assigning users to appropriate roles with proper scoping.
|
|
|
|
### Step 1: Define Company-Wide Features
|
|
|
|
Features represent specific permissions that can be checked in your application. Let's define features that match our TechCorp organizational structure:
|
|
|
|
```sql
|
|
-- System Administration Features
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'manage_all_users');
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'access_all_departments');
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'view_all_salaries');
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'manage_system_settings');
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'view_audit_logs');
|
|
SELECT public.c77_rbac_grant_feature('system_admin', 'export_all_data');
|
|
|
|
-- Department Management Features
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'view_dept_employees');
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'manage_dept_projects');
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'approve_dept_expenses');
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'view_dept_salaries');
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'create_dept_documents');
|
|
SELECT public.c77_rbac_grant_feature('dept_manager', 'view_confidential_docs');
|
|
|
|
-- Regular Employee Features
|
|
SELECT public.c77_rbac_grant_feature('employee', 'view_own_profile');
|
|
SELECT public.c77_rbac_grant_feature('employee', 'update_own_profile');
|
|
SELECT public.c77_rbac_grant_feature('employee', 'view_company_handbook');
|
|
SELECT public.c77_rbac_grant_feature('employee', 'submit_expenses');
|
|
SELECT public.c77_rbac_grant_feature('employee', 'view_own_expenses');
|
|
SELECT public.c77_rbac_grant_feature('employee', 'access_internal_docs');
|
|
|
|
-- Project Team Features
|
|
SELECT public.c77_rbac_grant_feature('project_member', 'view_project_details');
|
|
SELECT public.c77_rbac_grant_feature('project_member', 'edit_project_documents');
|
|
SELECT public.c77_rbac_grant_feature('project_member', 'view_project_expenses');
|
|
SELECT public.c77_rbac_grant_feature('project_member', 'submit_project_expenses');
|
|
|
|
SELECT public.c77_rbac_grant_feature('project_lead', 'manage_project_team');
|
|
SELECT public.c77_rbac_grant_feature('project_lead', 'approve_project_expenses');
|
|
SELECT public.c77_rbac_grant_feature('project_lead', 'create_project_documents');
|
|
|
|
-- Contractor Features (limited access)
|
|
SELECT public.c77_rbac_grant_feature('contractor', 'view_own_profile');
|
|
SELECT public.c77_rbac_grant_feature('contractor', 'view_assigned_projects');
|
|
SELECT public.c77_rbac_grant_feature('contractor', 'submit_expenses');
|
|
SELECT public.c77_rbac_grant_feature('contractor', 'access_project_docs');
|
|
|
|
-- HR Specific Features
|
|
SELECT public.c77_rbac_grant_feature('hr_staff', 'view_all_employees');
|
|
SELECT public.c77_rbac_grant_feature('hr_staff', 'manage_employee_data');
|
|
SELECT public.c77_rbac_grant_feature('hr_staff', 'access_hr_documents');
|
|
SELECT public.c77_rbac_grant_feature('hr_staff', 'view_salary_data');
|
|
|
|
-- Finance Specific Features
|
|
SELECT public.c77_rbac_grant_feature('finance_staff', 'view_all_expenses');
|
|
SELECT public.c77_rbac_grant_feature('finance_staff', 'approve_expenses');
|
|
SELECT public.c77_rbac_grant_feature('finance_staff', 'view_budget_data');
|
|
SELECT public.c77_rbac_grant_feature('finance_staff', 'access_financial_docs');
|
|
|
|
-- Sales Specific Features
|
|
SELECT public.c77_rbac_grant_feature('sales_staff', 'view_sales_data');
|
|
SELECT public.c77_rbac_grant_feature('sales_staff', 'manage_customer_info');
|
|
SELECT public.c77_rbac_grant_feature('sales_staff', 'access_sales_docs');
|
|
```
|
|
|
|
### Step 2: Sync Admin Features
|
|
|
|
The `admin` role should have access to all features. Let's sync all existing features to the admin role:
|
|
|
|
```sql
|
|
-- Make sure system admin gets all features
|
|
SELECT public.c77_rbac_sync_admin_features();
|
|
|
|
-- Check what features were granted to admin
|
|
SELECT * FROM public.c77_rbac_get_role_features('admin');
|
|
|
|
-- Also sync features to our system_admin role
|
|
SELECT public.c77_rbac_sync_admin_features();
|
|
```
|
|
|
|
### Step 3: Assign Roles to Users
|
|
|
|
Now we'll assign our TechCorp users to appropriate roles with proper scoping:
|
|
|
|
```sql
|
|
-- System Administrator (Alice)
|
|
SELECT public.c77_rbac_assign_subject('1', 'system_admin', 'global', 'all');
|
|
|
|
-- Department Managers
|
|
SELECT public.c77_rbac_assign_subject('101', 'dept_manager', 'department', 'ENG'); -- Bob
|
|
SELECT public.c77_rbac_assign_subject('201', 'dept_manager', 'department', 'SALES'); -- Frank
|
|
SELECT public.c77_rbac_assign_subject('301', 'dept_manager', 'department', 'HR'); -- Iris
|
|
SELECT public.c77_rbac_assign_subject('401', 'dept_manager', 'department', 'FIN'); -- Kelly
|
|
SELECT public.c77_rbac_assign_subject('501', 'dept_manager', 'department', 'MKT'); -- Maya
|
|
|
|
-- HR Staff (need special access across departments)
|
|
SELECT public.c77_rbac_assign_subject('301', 'hr_staff', 'global', 'all'); -- Iris (manager)
|
|
SELECT public.c77_rbac_assign_subject('302', 'hr_staff', 'global', 'all'); -- Jack
|
|
|
|
-- Finance Staff (need expense access across departments)
|
|
SELECT public.c77_rbac_assign_subject('401', 'finance_staff', 'global', 'all'); -- Kelly (manager)
|
|
SELECT public.c77_rbac_assign_subject('402', 'finance_staff', 'global', 'all'); -- Liam
|
|
|
|
-- Regular Employees (department-scoped)
|
|
SELECT public.c77_rbac_assign_subject('102', 'employee', 'department', 'ENG');
|
|
SELECT public.c77_rbac_assign_subject('103', 'employee', 'department', 'ENG');
|
|
SELECT public.c77_rbac_assign_subject('202', 'employee', 'department', 'SALES');
|
|
SELECT public.c77_rbac_assign_subject('203', 'employee', 'department', 'SALES');
|
|
SELECT public.c77_rbac_assign_subject('502', 'employee', 'department', 'MKT');
|
|
|
|
-- Contractors (department-scoped with limited access)
|
|
SELECT public.c77_rbac_assign_subject('104', 'contractor', 'department', 'ENG');
|
|
|
|
-- Project-specific roles
|
|
SELECT public.c77_rbac_assign_subject('101', 'project_lead', 'project', '1'); -- Bob leads Portal project
|
|
SELECT public.c77_rbac_assign_subject('103', 'project_lead', 'project', '2'); -- Dave leads Mobile project
|
|
SELECT public.c77_rbac_assign_subject('102', 'project_member', 'project', '1'); -- Carol on Portal
|
|
SELECT public.c77_rbac_assign_subject('102', 'project_member', 'project', '2'); -- Carol on Mobile
|
|
SELECT public.c77_rbac_assign_subject('104', 'project_member', 'project', '1'); -- Eve on Portal
|
|
|
|
-- Bulk assign basic employee role to all the additional users we created
|
|
SELECT * FROM public.c77_rbac_bulk_assign_subjects(
|
|
(SELECT array_agg(id::text) FROM users WHERE id BETWEEN 1001 AND 1050),
|
|
'employee',
|
|
'department',
|
|
'ENG' -- Assign them all to engineering for this example
|
|
);
|
|
```
|
|
|
|
### Step 4: Verify Role Assignments
|
|
|
|
Let's check that our role assignments are working correctly:
|
|
|
|
```sql
|
|
-- Check Alice's (admin) permissions
|
|
SELECT 'Alice (System Admin) - Roles:' as info;
|
|
SELECT * FROM public.c77_rbac_get_user_roles('1');
|
|
|
|
-- Check Bob's (engineering manager) permissions
|
|
SELECT 'Bob (Engineering Manager) - Roles:' as info;
|
|
SELECT * FROM public.c77_rbac_get_user_roles('101');
|
|
|
|
-- Check Carol's (developer) permissions
|
|
SELECT 'Carol (Developer) - Roles:' as info;
|
|
SELECT * FROM public.c77_rbac_get_user_roles('102');
|
|
|
|
-- Check Iris's (HR manager) permissions
|
|
SELECT 'Iris (HR Manager) - Roles:' as info;
|
|
SELECT * FROM public.c77_rbac_get_user_roles('301');
|
|
|
|
-- Check system summary
|
|
SELECT 'System Summary:' as info;
|
|
SELECT * FROM public.c77_rbac_summary;
|
|
```
|
|
|
|
### Step 5: Understanding RBAC Scoping
|
|
|
|
Let's explore how different scoping patterns work in our system:
|
|
|
|
```sql
|
|
-- Global scope (system-wide access)
|
|
-- Example: Alice has system_admin role with global/all scope
|
|
SELECT 'Global Admin Access Example:' as demo;
|
|
SELECT public.c77_rbac_can_access('manage_all_users', '1', 'global', 'all') as alice_can_manage_all;
|
|
|
|
-- Department scope (department-specific access)
|
|
-- Example: Bob can manage engineering department but not sales
|
|
SELECT 'Department Scope Examples:' as demo;
|
|
SELECT public.c77_rbac_can_access('manage_dept_projects', '101', 'department', 'ENG') as bob_can_manage_eng;
|
|
SELECT public.c77_rbac_can_access('manage_dept_projects', '101', 'department', 'SALES') as bob_cannot_manage_sales;
|
|
|
|
-- Project scope (project-specific access)
|
|
-- Example: Carol is a member of projects 1 and 2
|
|
SELECT 'Project Scope Examples:' as demo;
|
|
SELECT public.c77_rbac_can_access('view_project_details', '102', 'project', '1') as carol_can_view_proj1;
|
|
SELECT public.c77_rbac_can_access('view_project_details', '102', 'project', '3') as carol_cannot_view_proj3;
|
|
|
|
-- Cross-department access for special roles
|
|
-- Example: Iris (HR) can access all departments
|
|
SELECT 'Cross-Department Access Example:' as demo;
|
|
SELECT public.c77_rbac_can_access('view_all_employees', '301', 'global', 'all') as iris_can_see_all;
|
|
```
|
|
|
|
### Step 6: Create Role Hierarchy Visualization
|
|
|
|
Let's create a query to visualize our role hierarchy:
|
|
|
|
```sql
|
|
-- Create a comprehensive view of our RBAC setup
|
|
SELECT 'TechCorp RBAC Role Distribution:' as title;
|
|
|
|
SELECT
|
|
r.name as role_name,
|
|
sr.scope_type,
|
|
sr.scope_id,
|
|
count(*) as user_count,
|
|
string_agg(s.external_id, ', ' ORDER BY s.external_id::integer) as user_ids
|
|
FROM public.c77_rbac_roles r
|
|
JOIN public.c77_rbac_subject_roles sr ON r.role_id = sr.role_id
|
|
JOIN public.c77_rbac_subjects s ON sr.subject_id = s.subject_id
|
|
GROUP BY r.name, sr.scope_type, sr.scope_id
|
|
ORDER BY r.name, sr.scope_type, sr.scope_id;
|
|
|
|
-- Show feature distribution across roles
|
|
SELECT 'Feature Distribution:' as title;
|
|
|
|
SELECT
|
|
r.name as role_name,
|
|
count(f.name) as feature_count,
|
|
string_agg(f.name, ', ' ORDER BY f.name) as features
|
|
FROM public.c77_rbac_roles r
|
|
JOIN public.c77_rbac_role_features rf ON r.role_id = rf.role_id
|
|
JOIN public.c77_rbac_features f ON rf.feature_id = f.feature_id
|
|
GROUP BY r.name
|
|
ORDER BY count(f.name) DESC, r.name;
|
|
```
|
|
|
|
**✅ Checkpoint 3:** You now have a complete RBAC setup with realistic corporate roles!
|
|
|
|
---
|
|
|
|
## Understanding Our RBAC Structure
|
|
|
|
### Role Hierarchy
|
|
1. **System Admin** (`system_admin`)
|
|
- Scope: `global/all`
|
|
- Access: Everything across all departments and projects
|
|
- Users: Alice (ID: 1)
|
|
|
|
2. **Department Managers** (`dept_manager`)
|
|
- Scope: `department/[DEPT_CODE]`
|
|
- Access: Full control within their department
|
|
- Users: Bob (ENG), Frank (SALES), Iris (HR), Kelly (FIN), Maya (MKT)
|
|
|
|
3. **Specialized Staff**
|
|
- **HR Staff** (`hr_staff`): Global access to employee data
|
|
- **Finance Staff** (`finance_staff`): Global access to financial data
|
|
- **Sales Staff** (`sales_staff`): Access to sales-specific features
|
|
|
|
4. **Regular Employees** (`employee`)
|
|
- Scope: `department/[DEPT_CODE]`
|
|
- Access: Basic departmental access and own data
|
|
|
|
5. **Project Roles**
|
|
- **Project Leads** (`project_lead`): Scope: `project/[PROJECT_ID]`
|
|
- **Project Members** (`project_member`): Scope: `project/[PROJECT_ID]`
|
|
|
|
6. **Contractors** (`contractor`)
|
|
- Scope: `department/[DEPT_CODE]` or `project/[PROJECT_ID]`
|
|
- Access: Limited, task-specific access
|
|
|
|
### Key Scopes Used
|
|
- **`global/all`**: System-wide access (admins, HR, finance)
|
|
- **`department/[CODE]`**: Department-specific access (ENG, SALES, HR, FIN, MKT)
|
|
- **`project/[ID]`**: Project-specific access (1, 2, 3, 4, 5)
|
|
|
|
### Permission Patterns
|
|
- **Inheritance**: Users can have multiple roles with different scopes
|
|
- **Escalation**: `global/all` scope overrides specific scopes
|
|
- **Isolation**: Department and project scopes provide isolation
|
|
- **Flexibility**: Same user can have different roles in different contexts
|
|
|
|
---
|
|
|
|
## Advanced Role Management
|
|
|
|
### Adding New Roles Dynamically
|
|
|
|
```sql
|
|
-- Example: Create a "Senior Developer" role with enhanced permissions
|
|
SELECT public.c77_rbac_grant_feature('senior_developer', 'view_project_details');
|
|
SELECT public.c77_rbac_grant_feature('senior_developer', 'edit_project_documents');
|
|
SELECT public.c77_rbac_grant_feature('senior_developer', 'mentor_junior_developers');
|
|
SELECT public.c77_rbac_grant_feature('senior_developer', 'approve_code_reviews');
|
|
|
|
-- Assign Dave as a senior developer in the engineering department
|
|
SELECT public.c77_rbac_assign_subject('103', 'senior_developer', 'department', 'ENG');
|
|
|
|
-- Verify the assignment
|
|
SELECT * FROM public.c77_rbac_get_user_roles('103');
|
|
```
|
|
|
|
### Bulk Role Operations
|
|
|
|
```sql
|
|
-- Example: Assign all engineering employees to a "code_reviewer" role
|
|
-- First create the role
|
|
SELECT public.c77_rbac_grant_feature('code_reviewer', 'review_code');
|
|
SELECT public.c77_rbac_grant_feature('code_reviewer', 'comment_on_pull_requests');
|
|
|
|
-- Bulk assign to engineering employees
|
|
SELECT * FROM public.c77_rbac_bulk_assign_subjects(
|
|
ARRAY['101', '102', '103', '104'], -- Engineering team
|
|
'code_reviewer',
|
|
'department',
|
|
'ENG'
|
|
);
|
|
```
|
|
|
|
### Temporary Access Patterns
|
|
|
|
```sql
|
|
-- Example: Grant temporary access for a cross-departmental project
|
|
-- Marketing person needs temporary engineering access for a joint project
|
|
SELECT public.c77_rbac_assign_subject('502', 'project_member', 'project', '1');
|
|
|
|
-- Later, you can revoke this access
|
|
-- SELECT public.c77_rbac_revoke_subject_role('502', 'project_member', 'project', '1');
|
|
```
|
|
|
|
---
|
|
|
|
## What's Next?
|
|
|
|
Now that we have a comprehensive RBAC system set up, in **Part 4** we'll implement Row-Level Security (RLS) policies that will automatically enforce these permissions at the database level:
|
|
|
|
- Apply RLS policies to our TechCorp tables
|
|
- Implement sophisticated business rules for document access
|
|
- Create multi-level security controls
|
|
- Test automatic data filtering based on user roles
|
|
|
|
**Continue to [Part 4: Row-Level Security](TUTORIAL-Part4.md)**
|
|
|
|
---
|
|
|
|
## Chapter Summary
|
|
|
|
In this chapter, you've successfully:
|
|
|
|
### ✅ Created a Comprehensive Permission System
|
|
- **40+ features** covering all aspects of TechCorp operations
|
|
- **10+ roles** with realistic corporate hierarchy
|
|
- **65+ user assignments** with proper scoping
|
|
|
|
### ✅ Implemented Advanced Scoping Patterns
|
|
- **Global access** for system admins and cross-departmental roles
|
|
- **Department isolation** for managers and employees
|
|
- **Project-based collaboration** for cross-functional teams
|
|
- **Contractor limitations** for external workers
|
|
|
|
### ✅ Demonstrated RBAC Flexibility
|
|
- **Multiple roles per user** (e.g., department manager + project lead)
|
|
- **Hierarchical permissions** (global overrides departmental)
|
|
- **Dynamic role assignment** for changing business needs
|
|
- **Bulk operations** for efficient management
|
|
|
|
### ✅ Established Security Foundation
|
|
- **Role-based feature access** with proper validation
|
|
- **Scoped permissions** preventing unauthorized access
|
|
- **Audit-ready structure** with timestamps and tracking
|
|
- **Scalable design** that grows with organizational needs
|
|
|
|
The RBAC system is now ready for Row-Level Security implementation, which will automatically enforce these permissions at the database query level. |