Skip to main content

Authorization Overview

Overview

ASCEND implements enterprise-grade authorization with a 6-level role-based access control (RBAC) hierarchy, 23+ granular permissions, separation of duties (SoD) for high-risk operations, and database-enforced multi-tenant isolation via PostgreSQL Row-Level Security (RLS).

Why It Matters

Authorization ensures the right people have access to the right resources:

  • Least Privilege: Users only have permissions necessary for their role
  • Separation of Duties: Critical operations require multiple approvers
  • Multi-Tenant Isolation: Organizations cannot access each other's data
  • Audit Compliance: All access decisions are logged and traceable
  • Risk-Based Access: High-risk actions require elevated permissions

Architecture

Authorization Flow

+------------------+     +------------------+     +------------------+
| Authenticated | | RBAC Engine | | RLS Enforcement |
| Request | | | | (PostgreSQL) |
+--------+---------+ +--------+---------+ +--------+---------+
| | |
| 1. User Context | |
| (from auth) | |
+----------------------->| |
| | |
| | 2. Check Role Level |
| | |
| | 3. Check Permissions |
| | |
| | 4. Check SoD Rules |
| | |
| | 5. Set RLS Context |
| +----------------------->|
| | |
| | | 6. Enforce
| | | Tenant
| | | Isolation
| | |
| 7. Authorization | |
| Decision | |
|<-----------------------+ |

Authorization Components

ComponentPurposeImplementation
RBAC EngineRole and permission checksrbac_manager.py
RLS EnforcementMulti-tenant data isolationPostgreSQL policies
SoD RulesDual-approval requirementsseparation_of_duties dict
Permission DecoratorsEndpoint protection@require_permission()

RBAC Model

6-Level Role Hierarchy

Level 5: EXECUTIVE    ─────────────────────────────────────┐
│ │
│ All privileges + critical overrides │
│ │
Level 4: ADMIN ────────────────────────────────┐ │
│ │ │
│ Full system access except overrides │ │
│ │ │
Level 3: MANAGER ───────────────────────────┐ │ │
│ │ │ │
│ Authorization + approve LOW/MEDIUM │ │ │
│ │ │ │
Level 2: POWER ──────────────────────┐ │ │ │
│ │ │ │ │
│ Analytics + alerts + ack │ │ │ │
│ │ │ │ │
Level 1: BASIC ─────────────────┐ │ │ │ │
│ │ │ │ │ │
│ Dashboard view only │ │ │ │ │
│ │ │ │ │ │
Level 0: RESTRICTED ─────────────────┴────┴────┴────┴────┘

│ No permissions (suspended users)

Role Summary

LevelRoleDescriptionKey Permissions
0RESTRICTEDSuspended/probationaryNone
1BASICStandard usersDashboard view
2POWERPower usersAnalytics, alerts, acknowledge
3MANAGERManagersAuthorization, approve LOW/MEDIUM
4ADMINAdministratorsFull access, approve HIGH
5EXECUTIVEExecutivesAll + critical overrides

Full RBAC Documentation

Permission Categories

23+ Granular Permissions

CategoryPermissionsDescription
Dashboardview, exportDashboard access
Analyticsview, reports, exportAnalytics features
Alertsview, acknowledge, correlate, dismissAlert management
Rulesview, create, modify, deleteRule configuration
Authorizationview_pending, approve_low/medium/high/critical, emergency_overrideAction approval
Usersview, create, modify, delete, reset_password, manage_rolesUser management
Auditview, export, deleteAudit log access
Systemconfig, backup, maintenanceSystem administration

Full Permissions Reference

Separation of Duties (SoD)

Risk-Based Approval Requirements

Risk LevelScore RangeRequired ApproversRequired Roles
Low0-491MANAGER+
Medium50-691MANAGER+
High70-892ADMIN + ADMIN
Critical90-1002EXECUTIVE (different departments)

SoD Rules

RuleDescriptionRequirements
high_risk_approvalHigh-risk actions (70-89)2 approvers, cannot approve own
critical_risk_approvalCritical actions (90-100)2 EXECUTIVE, different departments
user_role_changesRole changesMANAGER + ADMIN
emergency_overrideEmergency bypass2 EXECUTIVE + justification

SoD Implementation

separation_of_duties = {
"high_risk_approval": {
"description": "High-risk actions require dual approval",
"risk_threshold": 70,
"required_approvers": 2,
"required_levels": [AccessLevel.ADMIN, AccessLevel.EXECUTIVE],
"cannot_approve_own": True
},
"critical_risk_approval": {
"description": "Critical actions require executive + admin approval",
"risk_threshold": 90,
"required_approvers": 2,
"required_levels": [AccessLevel.EXECUTIVE],
"required_different_departments": True,
"cannot_approve_own": True
},
"user_role_changes": {
"description": "User role changes require manager + admin",
"required_approvers": 2,
"required_levels": [AccessLevel.MANAGER, AccessLevel.ADMIN],
"cannot_approve_own": True
},
"emergency_override": {
"description": "Emergency overrides require dual executive approval",
"required_approvers": 2,
"required_levels": [AccessLevel.EXECUTIVE],
"required_justification": True,
"audit_immediately": True
}
}

Row-Level Security (RLS)

Multi-Tenant Isolation

PostgreSQL RLS ensures organizations cannot access each other's data:

-- Enable RLS on table
ALTER TABLE agent_actions ENABLE ROW LEVEL SECURITY;

-- Create isolation policy
CREATE POLICY org_isolation ON agent_actions
FOR ALL
USING (organization_id = current_setting('app.current_organization_id')::integer);

Session Context Setting

# Set RLS context after authentication
db.execute(text(f"SET LOCAL app.current_organization_id = {organization_id}"))

# All subsequent queries automatically filtered by organization_id
agents = db.query(Agent).all() # Only returns agents for current org

Authentication Bootstrap

For authentication lookup (before org is known), ASCEND uses a SECURITY DEFINER function:

-- Bypasses RLS only for authentication lookup
CREATE FUNCTION auth_lookup_api_key(prefix VARCHAR)
RETURNS TABLE(...) AS $$
BEGIN
RETURN QUERY SELECT ... FROM api_keys WHERE key_prefix = prefix;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

Configuration

Environment Variables

# RBAC Configuration
DEFAULT_USER_ROLE=basic
REQUIRE_SOD_FOR_HIGH_RISK=true
SOD_HIGH_RISK_THRESHOLD=70
SOD_CRITICAL_RISK_THRESHOLD=90

# RLS Configuration
ENABLE_RLS=true
RLS_FAIL_OPEN=false # If true, disables RLS on error (NOT RECOMMENDED)

Organization-Level Settings

{
"auth_config": {
"default_role": "basic",
"require_sod": true,
"sod_thresholds": {
"high": 70,
"critical": 90
},
"allowed_roles": ["basic", "power", "manager", "admin"],
"role_approval_required": ["admin", "executive"]
}
}

Usage

Permission Check in Code

from rbac_manager import enterprise_rbac, require_permission, Permission

# Check permission programmatically
if enterprise_rbac.has_permission(user.access_level, Permission.ALERTS_ACKNOWLEDGE):
# User can acknowledge alerts
pass

# Decorator-based check
@require_permission(Permission.RULES_CREATE)
async def create_rule(current_user: dict, rule_data: dict):
# Only users with rules.create permission can access
pass

Risk-Based Approval Check

from rbac_manager import enterprise_rbac

# Check if user can approve risk level
can_approve = enterprise_rbac.can_approve_risk_level(
user_access_level=user.access_level,
risk_score=75 # High risk
)

# Check SoD requirements
sod_requirement = enterprise_rbac.requires_separation_of_duties(
action_type="approval",
risk_score=75
)

if sod_requirement:
# Requires dual approval
required_approvers = sod_requirement["required_approvers"]

FastAPI Dependency

from dependencies_rbac import require_admin_role, require_minimum_level

# Require admin role
@router.post("/users")
async def create_user(
user_data: UserCreate,
current_user: dict = Depends(require_admin_role)
):
pass

# Require minimum access level
@router.get("/reports")
async def get_reports(
current_user: dict = Depends(require_minimum_level(AccessLevel.MANAGER))
):
pass

Fail-Secure Behavior

ScenarioResponseHTTP Status
Missing roleAssume RESTRICTED (level 0)N/A
Permission check failsDENY403
Role lookup errorDENY403
SoD check failsRequire additional approval403
RLS context not setReturn empty resultsN/A
RLS policy errorFAIL operation500

Compliance Mapping

FrameworkControlImplementation
SOC 2CC6.1Role-based access, least privilege
SOC 2CC6.2Separation of duties
SOC 2CC6.3Role-based authorization
HIPAA164.312(a)(1)Access control, unique user IDs
PCI-DSSReq 7.1Need-to-know access
PCI-DSSReq 7.2Access control systems
NIST 800-53AC-2Account management
NIST 800-53AC-3Access enforcement
NIST 800-53AC-5Separation of duties
NIST 800-53AC-6Least privilege

Verification

Check User Permissions

curl -X GET https://api.ascend.io/v1/auth/permissions \
-H "Authorization: Bearer $TOKEN"

# Response
{
"user_id": 123,
"access_level": 4,
"role_name": "Administrator",
"permissions": [
"dashboard.view",
"dashboard.export",
"analytics.view",
"analytics.reports",
"alerts.view",
"alerts.acknowledge",
...
],
"can_approve": {
"low": true,
"medium": true,
"high": true,
"critical": false
},
"requires_sod_for_high_risk": true
}

Test Permission Enforcement

# Try to access admin endpoint without permission
curl -X POST https://api.ascend.io/v1/users \
-H "Authorization: Bearer $BASIC_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "new@example.com"}'

# Expected: 403 Forbidden
{
"detail": "Insufficient permissions. Required: users.create"
}

Verify RLS Isolation

# As org 1 user, try to access org 2 data
curl -X GET https://api.ascend.io/v1/agents/999 \
-H "Authorization: Bearer $ORG1_TOKEN"

# Expected: 404 Not Found (RLS prevents access)
{
"detail": "Agent not found"
}

Next Steps