Skip to content

[FEATURE][POLICY]: Unified policy decision point (PDP) - Cedar/OPA/native abstraction #2223

@crivetimihai

Description

@crivetimihai

🔌 Feature: Unified Policy Decision Point (PDP) - Cedar/OPA/Native Abstraction

Goal

Create a Unified Policy Decision Point (PDP) that provides a single interface for all policy engines (Cedar, OPA, Native RBAC, MAC), enabling consistent policy evaluation, combination logic, and decision caching across the gateway.

Why Now?

  1. Fragmented Engines: Cedar, OPA, and native RBAC plugins exist but have different interfaces and don't combine decisions
  2. No Abstraction: Code calling policy engines must know which engine to use—not portable
  3. Combination Logic Missing: Organizations want policies from multiple engines to work together (e.g., RBAC AND MAC)
  4. Caching Opportunity: Policy decisions can be cached to improve performance—currently not implemented
  5. Foundation Required: The Policy-as-Code platform ([EPIC][SECURITY]: Policy-as-code security and compliance automation platform #2222) needs a unified PDP as its core

📖 User Stories

US-1: Developer - Single Policy Check Interface

As a Gateway Developer
I want a single interface to check access policies
So that I don't need to know which policy engine is configured

Acceptance Criteria:

Given multiple policy engines are configured (Cedar, OPA, native):
When I call the PDP:
  decision = await pdp.check_access(
      subject=Subject(email="user@example.com", roles=["developer"]),
      action="tools.invoke",
      resource=Resource(type="tool", id="db-query", server="prod-db"),
      context=Context(ip="10.0.0.1", time=now())
  )
Then the PDP:
  - Evaluates all configured engines in parallel
  - Combines decisions per configuration (all_must_allow | any_allow)
  - Returns a unified AccessDecision with:
    - decision: allow | deny
    - reason: explanation
    - matching_policies: list of policies that matched
    - duration_ms: evaluation time
US-2: Platform Admin - Configure Engine Combination

As a Platform Administrator
I want to configure how policy engine decisions are combined
So that I can implement defense-in-depth with multiple engines

Acceptance Criteria:

Given I configure the PDP:
  pdp:
    engines: [cedar, opa, native, mac]
    combination_mode: "all_must_allow"
    default_decision: "deny"
When a request is evaluated:
Then ALL engines must return "allow" for access to be granted
And if ANY engine returns "deny", access is denied
And the denying policy is recorded for audit

🏗 Architecture

PDP Interface

class PolicyDecisionPoint:
    """Unified interface for all policy engines."""
    
    async def check_access(
        self,
        subject: Subject,
        action: str,
        resource: Resource,
        context: Context
    ) -> AccessDecision:
        """Evaluate access request against all configured engines."""
        
    async def explain_decision(
        self,
        subject: Subject,
        action: str,
        resource: Resource,
        context: Context
    ) -> DecisionExplanation:
        """Get detailed explanation of why access was granted/denied."""
        
    async def get_effective_permissions(
        self,
        subject: Subject,
        context: Context
    ) -> List[Permission]:
        """Get all permissions the subject has."""

Engine Adapter Interface

class PolicyEngineAdapter(ABC):
    """Adapter interface for policy engines."""
    
    @abstractmethod
    async def evaluate(
        self,
        subject: Subject,
        action: str,
        resource: Resource,
        context: Context
    ) -> EngineDecision:
        """Evaluate request against this engine."""

📋 Implementation Tasks


⚙️ Configuration Example

pdp:
  engines:
    - name: cedar
      enabled: true
      priority: 1
    - name: opa
      enabled: true
      priority: 2
    - name: native
      enabled: true
      priority: 3
    - name: mac
      enabled: false
      priority: 4
      
  combination_mode: "all_must_allow"  # all_must_allow | any_allow | first_match
  default_decision: "deny"
  
  cache:
    enabled: true
    ttl_seconds: 60
    max_entries: 10000
    
  performance:
    timeout_ms: 1000
    parallel_evaluation: true

✅ Success Criteria

  • Single check_access() interface works for all engines
  • Cedar, OPA, Native, MAC adapters functional
  • Decision combination logic works correctly
  • Caching reduces evaluation time for repeat requests
  • Performance <10ms for 95th percentile (cached)
  • 80%+ test coverage
  • Documentation complete

🔗 Related Issues

Metadata

Metadata

Assignees

Labels

COULDP3: Nice-to-have features with minimal impact if left out; included if time permitsenhancementNew feature or requestpluginspythonPython / backend development (FastAPI)securityImproves securitysweng-group-5Group 5 - Policy-as-Code Security & Compliance AutomationtcdSwEng Projects

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions