Policy Engine Overview
Summary
The Policy Engine is the central service for managing authorization policies in Keymate. It provides APIs for creating, updating, and deleting policies across six authorization models (RBAC, ABAC, ReBAC, PBAC, RADAC, Dynamic), validates policy definitions before storage, and sends audit events for compliance tracking.
Why It Exists
Authorization systems require a dedicated service to manage the lifecycle of policies separate from runtime evaluation. This separation enables:
- Independent scaling — Policy management traffic patterns differ from evaluation traffic
- Clear ownership — A single service owns policy storage and validation
- Audit isolation — Policy changes are tracked independently from access decisions
- Multi-model support — Different authorization approaches coexist under unified management
Where It Fits in Keymate
The Policy Engine sits between policy authors (Admin Console, external systems) and runtime evaluation components (Access Gateway, Permission Gateway). It does not evaluate access requests — that responsibility belongs to the gateways.
Boundaries
This component covers:
- Policy CRUD operations via REST API
- Policy validation and business rules
- Multi-tenant policy isolation
- Policy templates for reusable patterns
- Audit event emission for policy changes
- Integration Hub webhook handling for attribute synchronization
This component does not cover:
- Runtime access evaluation → see Access Gateway
- Permission checks → see Authorization Decision Provider
- Relationship-based graph queries → see FGA Engine
- Policy authoring concepts → see Policy Model
How It Works
Policy Types
The Policy Engine supports six authorization models:
| Type | Description |
|---|---|
| RBAC | Role-Based Access Control — grants access based on user roles and groups |
| ABAC | Attribute-Based Access Control — evaluates conditions on user, resource, and environment attributes |
| ReBAC | Relationship-Based Access Control — queries relationship graphs via OpenFGA |
| PBAC | Policy-Based Access Control — composes multiple policies into a single decision |
| RADAC | Risk-Adaptive Dynamic Access Control — adjusts decisions based on risk scores |
| Dynamic | Custom evaluation logic for specialized scenarios |
Policy Structure
Every policy shares a common structure:
{
"id": 1,
"tenant": "acme-corp",
"name": "document-editor-access",
"description": "Allows editors to modify documents",
"enabled": true,
"policyType": "RBAC",
"status": "ENABLED",
"strategy": "AFFIRMATIVE",
"logic": "POSITIVE",
"isShared": false,
"version": "1.0.0",
"policy": {
// Type-specific content
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
Decision Strategy
The strategy field determines how multiple conditions combine:
| Strategy | Behavior |
|---|---|
AFFIRMATIVE | Any single "allow" permits access (logical OR) |
UNANIMOUS | All conditions must "allow" (logical AND) |
CONSENSUS | Majority of conditions decides |
Policy Logic
The logic field controls how the evaluation result is interpreted:
| Logic | Behavior |
|---|---|
POSITIVE | Result used as-is: true = allow, false = deny |
NEGATIVE | Result inverted: true = deny, false = allow (for exception rules) |
Policy Modes
Policies can be authored in two modes:
| Mode | Description |
|---|---|
CONDITIONS | Structured condition builder (UI-friendly) |
EXPRESSION | Free-form DSL expression (power users) |
Multi-Tenancy
Every policy belongs to a tenant. The tenant field provides automatic isolation — queries return only policies for the requesting tenant. The isShared flag allows policies to be visible across tenants while maintaining ownership.
API Surface
The Policy Engine exposes a REST API for policy CRUD operations:
- List and retrieve policies with pagination and filtering
- Create policies for each authorization model (RBAC, ABAC, ReBAC, PBAC, RADAC, Dynamic)
- Update and delete existing policies
- Manage templates for reusable policy patterns
Diagram
Example Scenario
Scenario
A platform administrator creates an RBAC policy that grants document editing access to users with the "editor" role.
Input
- Actor: Platform administrator via Admin Console
- Resource: Policy Engine REST API
- Action: Create RBAC policy
- Context:
{
"tenant": "acme-corp",
"name": "document-editor-access",
"description": "Grants edit access to editors",
"enabled": true,
"status": "ENABLED",
"strategy": "AFFIRMATIVE",
"logic": "POSITIVE",
"policy": {
"roles": [
{
"id": "editor-role-id",
"name": "editor",
"client": "content-management",
"required": true
}
],
"groups": [],
"fetchRoles": false,
"generic": false,
"mode": "CONDITIONS"
}
}
Expected Outcome
- Result: Policy created with assigned ID and timestamps
- Why: The Policy Engine validates the request structure, checks tenant authorization, persists the policy, sends an audit event to the Audit Collector, and returns the created policy
Common Misunderstandings
-
"The Policy Engine evaluates access requests" — The Policy Engine manages policy definitions. Runtime evaluation happens in the Access Gateway and Permission Gateway, which fetch policies from the Policy Engine.
-
"PBAC and ReBAC are the same" — PBAC (Policy-Based) composes multiple policies into a single decision using strategies. ReBAC (Relationship-Based) evaluates graph relationships. They serve different purposes and can be combined.
-
"Disabling a policy deletes it" — Setting
enabled: falseorstatus: DISABLEDkeeps the policy in storage but excludes it from active evaluation. Deletion requires a separate DELETE request.
The isShared field controls cross-tenant visibility. A shared policy can be referenced by other tenants but is still owned by the creating tenant. Use with caution in multi-tenant deployments.
Design Notes / Best Practices
-
Use policy templates for common authorization patterns. Templates reduce duplication and ensure consistency across tenants.
-
Prefer AFFIRMATIVE strategy for additive permission models where any matching role grants access. Use UNANIMOUS when all conditions must be satisfied (defense in depth).
-
Leverage NEGATIVE logic for exception rules. Instead of duplicating allow rules with exclusions, create a deny policy with
logic: NEGATIVEthat triggers on specific conditions. -
Version your policies using the
versionfield. Versioning helps track policy evolution and supports rollback decisions.
When combining RBAC and ABAC in a PBAC composite policy, place the RBAC check first. Role checks are faster than attribute evaluations, enabling early rejection.
Related Use Cases
- Managing role-based permissions for enterprise applications
- Creating attribute-based policies for data classification
- Composing multiple authorization models for complex access control
- Sharing policy templates across tenants
Related Docs
Policy Model Concepts
DSL, dual-mode authoring, simulation
Authorization Models
RBAC, ABAC, ReBAC, PBAC concepts
Audit & Observability
Decision traces and event capture
Integration Hub
Connector management for external systems
FAQ
Does the Policy Engine support real-time policy updates?
Yes. Policy changes made via the REST API take effect immediately. Consuming components (Access Gateway, Permission Gateway) implement caching strategies with appropriate TTLs to balance performance and freshness.
How does multi-tenancy work in the Policy Engine?
Every policy has a tenant field that isolates it to a specific tenant. Queries automatically filter by tenant. The isShared flag allows policies to be visible across tenants while maintaining ownership.
Can I combine multiple authorization models in one policy?
Yes, using PBAC (Policy-Based Access Control). A PBAC policy references other policies by ID and combines their results using the configured decision strategy (AFFIRMATIVE, UNANIMOUS, or CONSENSUS).
What happens if a policy validation fails?
The Policy Engine returns a 400 Bad Request with details about the validation error. Common issues include missing required fields, invalid enum values, or referencing non-existent policies in PBAC compositions.