Skip to content

[FEATURE]: Centralized configurable RBAC/ABAC policy engine #2019

@crivetimihai

Description

@crivetimihai

Summary

Implement a centralized, configurable RBAC/ABAC policy engine that consolidates all access control decisions into a single, admin-configurable system. Currently, access control is scattered across multiple layers with hardcoded permissions, making it difficult to customize without code changes.

Current State Analysis

Access Control Decision Points (Scattered)

┌─────────────────────────────────────────────────────────────────────────────────┐
│                     CURRENT: Scattered Access Control                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐        │
│   │   Token     │   │   RBAC      │   │  Service    │   │   Route     │        │
│   │  Scoping    │   │ Middleware  │   │   Layer     │   │  Handler    │        │
│   │ Middleware  │   │ Decorator   │   │  Filtering  │   │   Logic     │        │
│   └──────┬──────┘   └──────┬──────┘   └──────┬──────┘   └──────┬──────┘        │
│          │                 │                 │                 │               │
│          ▼                 ▼                 ▼                 ▼               │
│   • Team membership  • Role perms     • Visibility      • is_admin check      │
│   • IP restrictions  • Admin bypass   • Owner check     • Custom logic        │
│   • Time windows     • Plugin hooks   • Team filter     • Hardcoded rules     │
│   • Server scoping   • Audit log      • Query mods                            │
│                                                                                 │
│   PROBLEMS: Inconsistent enforcement, no single source of truth,               │
│             hardcoded permissions, difficult to audit/configure                │
└─────────────────────────────────────────────────────────────────────────────────┘

What's Currently Hardcoded

Component Hardcoded Elements Location
Permissions tools.read, resources.create, etc. mcpgateway/db.py
Role scopes global, team, personal mcpgateway/db.py
Visibility levels public, team, private Multiple files
Time restrictions 9-17 UTC, Mon-Fri token_scoping.py
Admin bypass is_admin=True check Multiple middlewares
Team roles owner, member EmailTeamMember.role

Current Enforcement Layers

  1. TokenScopingMiddleware (middleware/token_scoping.py)

    • Team membership validation
    • Resource visibility filtering
    • Server-specific scoping
    • IP/CIDR restrictions
    • Time-based restrictions
    • Token-level permissions
  2. RBAC Decorators (middleware/rbac.py)

    • @require_permission() on routes
    • Role-based permission checks
    • Plugin hook integration
    • Admin bypass logic
  3. Service Layer (services/*_service.py)

    • Visibility filtering in queries
    • Owner-based access checks
    • Team membership filtering
  4. Route Handlers (main.py, admin.py)

    • Ad-hoc is_admin checks
    • Custom authorization logic

Proposed Solution: Unified Policy Engine

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────────┐
│                     PROPOSED: Centralized Policy Engine                         │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│                          ┌─────────────────────┐                                │
│                          │   Policy Engine     │                                │
│                          │   (Single Source    │                                │
│                          │    of Truth)        │                                │
│                          └──────────┬──────────┘                                │
│                                     │                                           │
│              ┌──────────────────────┼──────────────────────┐                    │
│              │                      │                      │                    │
│              ▼                      ▼                      ▼                    │
│   ┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐              │
│   │  Policy Store   │   │  Policy Cache   │   │  Audit Logger   │              │
│   │  (Database)     │   │  (Redis/Memory) │   │  (All Decisions)│              │
│   └─────────────────┘   └─────────────────┘   └─────────────────┘              │
│                                                                                 │
│   ┌─────────────────────────────────────────────────────────────┐              │
│   │                    Policy Definitions                        │              │
│   ├─────────────────────────────────────────────────────────────┤              │
│   │  • Permissions (configurable, not hardcoded)                │              │
│   │  • Roles (with inheritance chains)                          │              │
│   │  • Policies (ABAC rules with conditions)                    │              │
│   │  • Resource rules (per-resource permissions)                │              │
│   │  • Time/IP/context constraints                              │              │
│   └─────────────────────────────────────────────────────────────┘              │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Policy Definition Schema

# Example: policies.yaml (or database-stored)
permissions:
  - name: tools.read
    description: "Read tool definitions"
    resource_type: tool
    action: read
    
  - name: tools.execute
    description: "Execute tools"
    resource_type: tool
    action: execute
    # Can add custom permissions without code changes

roles:
  - name: viewer
    scope: global
    permissions:
      - tools.read
      - resources.read
      - prompts.read
      
  - name: developer
    scope: team
    inherits: viewer
    permissions:
      - tools.execute
      - resources.create
      
  - name: admin
    scope: global
    permissions: ["*"]

policies:
  # ABAC-style policies
  - name: team-resource-access
    description: "Team members can access team resources"
    effect: allow
    conditions:
      - resource.visibility == "team"
      - resource.team_id IN subject.teams
      
  - name: owner-full-access
    description: "Resource owners have full access"
    effect: allow
    conditions:
      - resource.owner_email == subject.email
      
  - name: business-hours-only
    description: "Restrict to business hours"
    effect: deny
    conditions:
      - context.hour < 9 OR context.hour > 17
      - subject.has_tag("restricted-hours")
      
  - name: ip-allowlist
    description: "IP-based access control"
    effect: allow
    conditions:
      - context.ip IN policy.allowed_cidrs

resource_rules:
  # Fine-grained per-resource permissions
  - resource_type: tool
    resource_id: "sensitive-tool-123"
    allowed_roles: [admin, security-team]
    denied_users: [contractor@example.com]

Policy Engine Interface

class PolicyEngine:
    """Centralized access control decision point."""
    
    async def check_access(
        self,
        subject: Subject,      # User/token info
        action: str,           # e.g., "read", "execute"
        resource: Resource,    # Resource being accessed
        context: Context       # Request context (IP, time, etc.)
    ) -> AccessDecision:
        """
        Single entry point for ALL access control decisions.
        
        Returns:
            AccessDecision with:
            - allowed: bool
            - reason: str
            - matching_policies: List[str]
            - audit_id: str
        """
        
    async def get_accessible_resources(
        self,
        subject: Subject,
        resource_type: str,
        action: str,
        context: Context
    ) -> ResourceFilter:
        """
        Returns filter criteria for list queries.
        Used by services to filter results efficiently.
        """

    async def explain_access(
        self,
        subject: Subject,
        action: str,
        resource: Resource,
        context: Context
    ) -> AccessExplanation:
        """
        Debug tool: explains why access was granted/denied.
        Shows all evaluated policies and their results.
        """

Admin UI for Policy Management

┌─────────────────────────────────────────────────────────────────┐
│  Admin UI → Access Control                                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│  │ Permissions │ │   Roles     │ │  Policies   │ │  Audit    │ │
│  └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │
│                                                                 │
│  Permissions:                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ [+] Add Permission                                       │   │
│  │                                                          │   │
│  │ ☑ tools.read      - Read tool definitions     [Edit][Del]│   │
│  │ ☑ tools.execute   - Execute tools             [Edit][Del]│   │
│  │ ☑ tools.create    - Create new tools          [Edit][Del]│   │
│  │ ☐ tools.admin     - Full tool management      [Edit][Del]│   │
│  │ ...                                                      │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  Policies:                                                      │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ [+] Add Policy                                           │   │
│  │                                                          │   │
│  │ ● team-resource-access     [Active]  [Edit] [Test]       │   │
│  │   IF resource.visibility = "team"                        │   │
│  │   AND resource.team_id IN subject.teams                  │   │
│  │   THEN ALLOW                                             │   │
│  │                                                          │   │
│  │ ● business-hours-only      [Active]  [Edit] [Test]       │   │
│  │   IF context.hour < 9 OR context.hour > 17               │   │
│  │   AND subject.has_restriction("business-hours")          │   │
│  │   THEN DENY with "Outside business hours"                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  Policy Tester:                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ Subject: [user@example.com    ▼]                         │   │
│  │ Action:  [execute             ▼]                         │   │
│  │ Resource:[tool:abc-123        ▼]                         │   │
│  │                                                          │   │
│  │ [Test Access]                                            │   │
│  │                                                          │   │
│  │ Result: ✅ ALLOWED                                       │   │
│  │ Matching policies:                                       │   │
│  │   • team-resource-access (user in team "developers")     │   │
│  │   • role:developer has permission tools.execute          │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Implementation Phases

Phase 1: Foundation (Core Engine)

  • Create PolicyEngine service with unified check_access() interface
  • Database models for configurable permissions, policies
  • Migration from hardcoded Permissions class to database
  • Consolidate all middleware checks to use PolicyEngine
  • Comprehensive audit logging for all decisions

Phase 2: ABAC Support

  • Policy condition expression language (simple DSL or JSON)
  • Context attributes (time, IP, request metadata)
  • Resource attributes (visibility, team, owner, tags)
  • Subject attributes (roles, teams, custom attributes)
  • Policy evaluation with AND/OR/NOT combinations

Phase 3: Admin UI

  • Permission management UI (CRUD)
  • Role management with inheritance visualization
  • Policy editor with syntax validation
  • Policy tester/simulator
  • Access decision audit viewer

Phase 4: Advanced Features

  • Fine-grained resource-level permissions
  • Policy versioning and rollback
  • Policy import/export (YAML/JSON)
  • External policy engine integration (OPA/Cedar)
  • SSO group → team/role mapping
  • Delegation and temporary access grants

Benefits

Current State Proposed State
Hardcoded permissions require code changes Admin-configurable permissions
Scattered enforcement across 4+ layers Single PolicyEngine entry point
No ABAC support Full ABAC with conditions
Limited audit trail Comprehensive decision logging
No policy testing Built-in policy simulator
Token scoping separate from RBAC Unified access control model
Admin bypass is all-or-nothing Granular admin permissions

Database Schema Changes

-- New tables for configurable RBAC
CREATE TABLE access_permissions (
    id UUID PRIMARY KEY,
    name VARCHAR(100) UNIQUE NOT NULL,
    description TEXT,
    resource_type VARCHAR(50),
    action VARCHAR(50),
    is_system BOOLEAN DEFAULT FALSE,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

CREATE TABLE access_policies (
    id UUID PRIMARY KEY,
    name VARCHAR(100) UNIQUE NOT NULL,
    description TEXT,
    effect VARCHAR(10) NOT NULL, -- 'allow' or 'deny'
    priority INTEGER DEFAULT 0,
    conditions JSONB NOT NULL, -- Policy conditions
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    created_by VARCHAR(255)
);

CREATE TABLE access_decisions (
    id UUID PRIMARY KEY,
    timestamp TIMESTAMP NOT NULL,
    subject_email VARCHAR(255),
    subject_type VARCHAR(50), -- 'user', 'token', 'service'
    action VARCHAR(50),
    resource_type VARCHAR(50),
    resource_id VARCHAR(255),
    decision VARCHAR(10), -- 'allow', 'deny'
    reason TEXT,
    matching_policies JSONB,
    context JSONB, -- IP, time, etc.
    request_id VARCHAR(100)
);

CREATE TABLE resource_access_rules (
    id UUID PRIMARY KEY,
    resource_type VARCHAR(50) NOT NULL,
    resource_id VARCHAR(255), -- NULL = all resources of type
    policy_id UUID REFERENCES access_policies(id),
    allowed_roles JSONB,
    denied_users JSONB,
    is_active BOOLEAN DEFAULT TRUE
);

API Endpoints

# Policy Management
GET    /admin/access/permissions       # List all permissions
POST   /admin/access/permissions       # Create permission
PUT    /admin/access/permissions/{id}  # Update permission
DELETE /admin/access/permissions/{id}  # Delete permission

GET    /admin/access/policies          # List all policies
POST   /admin/access/policies          # Create policy
PUT    /admin/access/policies/{id}     # Update policy
DELETE /admin/access/policies/{id}     # Delete policy

# Policy Testing
POST   /admin/access/test              # Test access decision
GET    /admin/access/explain           # Explain access for user/resource

# Audit
GET    /admin/access/audit             # Query access decisions
GET    /admin/access/audit/{id}        # Get decision details

# Export/Import
GET    /admin/access/export            # Export all policies
POST   /admin/access/import            # Import policies

Related Issues

References

Metadata

Metadata

Assignees

Labels

SHOULDP2: Important but not vital; high-value items that are not crucial for the immediate releasedatabaseenhancementNew feature or requestpythonPython / backend development (FastAPI)securityImproves securitysweng-group-5Group 5 - Policy-as-Code Security & Compliance AutomationtcdSwEng Projects

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions