Back to Blog

Three-Layer Permission Model: RBAC+ABAC+ReBAC Unified Design

coomia-dip implements a unified three-layer permission model: RBAC controls "who can do what," ABAC governs "under what conditions," and ReBAC determines "based on what relationships." These three layers are orchestrated by the PolicyEngineService with 8 operator types and zero-intrusion query rewriting for data access control. This article provides a comprehensive analysis from architecture design and data modeling through policy evaluation workflows to production best practices.

CoomiaPublished on September 14, 202514 min read
Share this articleTwitter / X

Series: S6 Platform Engineering · Article 1 | Level: Advanced | Reading Time: 18 min

Three-Layer Permission Model: RBAC+ABAC+ReBAC Unified Design

#TL;DR

coomia-dip implements a unified three-layer permission model: RBAC controls "who can do what," ABAC governs "under what conditions," and ReBAC determines "based on what relationships." These three layers are orchestrated by the PolicyEngineService with 8 operator types and zero-intrusion query rewriting for data access control. This article provides a comprehensive analysis from architecture design and data modeling through policy evaluation workflows to production best practices.

#1. Why a Three-Layer Permission Model

#1.1 Limitations of Single Models

In traditional enterprise applications, RBAC (Role-Based Access Control) is the most common permission model. However, as data platforms evolve, a single RBAC model faces significant challenges:

  • Insufficient granularity: RBAC can only control at the "role-resource" level and cannot enforce fine-grained control based on data attributes (such as classification level or geographic region)
  • Relationship blindness: RBAC cannot express authorization like "User A is the owner of Project X, therefore can access all data under Project X"
  • Policy explosion: When different departments, data levels, and time periods require different permissions, the number of roles grows exponentially

#1.2 Complementary Three-Layer Design

coomia-dip adopts a complementary three-layer permission model, where each layer addresses specific authorization challenges:

Code
+--------------------------------------------------+
|              PolicyEngineService                  |
|       (Unified Policy Evaluation Engine,          |
|              8 Operator Types)                    |
+--------------------------------------------------+
         |              |              |
    +--------+    +---------+    +---------+
    |  RBAC  |    |  ABAC   |    |  ReBAC  |
    |  Role  |    | Attribute|    | Relation|
    |  Layer |    |  Layer  |    |  Layer  |
    +--------+    +---------+    +---------+
    |        |    |         |    |         |
    | Roles  |    | Subject |    | Object  |
    | Perms  |    | Resource|    | Relation|
    | Rsrcs  |    | Environ.|    | Tuples  |
    +--------+    +---------+    +---------+
LayerQuestion AnsweredTypical Scenario
RBACWho can do what?Admins can create Ontologies
ABACUnder what conditions?Only during work hours, from intranet, on non-confidential data
ReBACBased on what relationships?Project owners can access all datasets under their project

#1.3 Comparison with Palantir Foundry

Palantir Foundry's permission system also employs a multi-layer design, but its implementation is closed-source. coomia-dip achieves equivalent capabilities through open-source:

CapabilityPalantir Foundrycoomia-dip
Role-based controlMultipass + Project rolesRBAC layer
Attribute-based controlMarking + ClassificationABAC layer
Relationship-based controlProject membershipReBAC layer (Zanzibar-style)
Query rewritingBuilt-in but opaqueZero-intrusion query rewrite
Data maskingBuilt-in6 masking modes
Data classificationMulti-tier classification7-tier classification (A1-D)

#2. PolicyEngineService Architecture

#2.1 Service Positioning

PolicyEngineService is the core security service within Control Layer (Control Layer), responsible for orchestrating policy evaluation across all three permission layers. It runs within a Spring Boot 3.x application and provides internal service calls via gRPC.

Code
+-------------------------------------------------------------+
|                    Control Layer: Control Layer                    |
|                                                             |
|  +-------------------+  +------------------+  +----------+ |
|  | PolicyEngine      |  | Classification   |  | DataMask | |
|  | Service           |  | Service          |  | Service  | |
|  |                   |  |                  |  |          | |
|  | - evaluatePolicy  |  | - classify       |  | - mask   | |
|  | - checkAccess     |  | - getLevel       |  | - unmask | |
|  | - rewriteQuery    |  | - autoClassify   |  |          | |
|  +-------------------+  +------------------+  +----------+ |
|           |                      |                  |       |
|  +----------------------------------------------------+    |
|  |             Policy Decision Point (PDP)             |    |
|  |  8 Operators: eq, ne, gt, lt, in, contains,        |    |
|  |               matches, between                      |    |
|  +----------------------------------------------------+    |
+-------------------------------------------------------------+

#2.2 Eight Policy Operators

PolicyEngineService supports 8 policy operators covering all comparison requirements for enterprise-grade permission management:

Code
+----------+-----------------+----------------------------------+
| Operator | Type            | Description                      |
+----------+-----------------+----------------------------------+
| eq       | Equality        | Exact attribute value match      |
| ne       | Inequality      | Attribute value mismatch         |
| gt       | Greater than    | Numeric/date greater than        |
| lt       | Less than       | Numeric/date less than           |
| in       | Set membership  | Attribute value in given set     |
| contains | Containment     | String/set contains sub-element  |
| matches  | Regex match     | Attribute matches regex pattern  |
| between  | Range check     | Attribute in range [min, max]    |
+----------+-----------------+----------------------------------+

#2.3 Policy Evaluation Flow

A complete policy evaluation flow proceeds as follows:

Code
Request Arrives
    |
    v
+-------------------+
| 1. Identity       |   Extract subject info from JWT/mTLS
|    Resolution      |
+-------------------+
    |
    v
+-------------------+
| 2. RBAC Check     |   Query role-permission mappings
|    (Fast Path)     |   Hit -> Direct allow/deny
+-------------------+
    |
    v (needs fine-grained control)
+-------------------+
| 3. ABAC Eval      |   Collect subject/resource/env attributes
|    (Attr Match)    |   Evaluate policy expressions with 8 ops
+-------------------+
    |
    v (needs relationship check)
+-------------------+
| 4. ReBAC Check    |   Traverse relationship graph
|    (Rel Traverse)  |   Check subject-resource relation paths
+-------------------+
    |
    v
+-------------------+
| 5. Policy Decision|   Merge three-layer results
|    (Decision)      |   DENY > ALLOW > NOT_APPLICABLE
+-------------------+
    |
    v
+-------------------+
| 6. Obligation     |   Trigger masking, auditing, etc.
|    Enforcement     |
+-------------------+

#2.4 Policy Combination Semantics

Results from the three layers are combined using the following semantics:

Java
public enum PolicyDecision {
    ALLOW,           // Explicitly allow
    DENY,            // Explicitly deny
    NOT_APPLICABLE   // Not applicable
}

// Combination rule: DENY-overrides
// Any layer returns DENY -> final DENY
// At least one ALLOW and no DENY -> final ALLOW
// All NOT_APPLICABLE -> final DENY (default deny)

This is the classic DENY-overrides combination strategy, ensuring security takes precedence.

#3. Data Model Design

#3.1 Core Entity Relationships

Code
+-------------+     +---------------+     +-------------+
|   Subject   |---->|  RoleBinding  |---->|    Role     |
|  (Principal) |     | (Role Binding)|     |   (Role)    |
+-------------+     +---------------+     +-------------+
                                               |
                                               v
                                          +-------------+
                                          | Permission  |
                                          | (Permission)|
                                          +-------------+
                                               |
                                               v
+-------------+     +---------------+     +-------------+
|  Resource   |<----|  PolicyRule   |---->| Condition   |
|  (Resource)  |     | (Policy Rule) |     | (Condition) |
+-------------+     +---------------+     +-------------+
                                               |
                                               v
+-------------+                           +-------------+
| Relation    |                           |  Operator   |
| Tuple       |                           | (Operator)  |
| (Rel Tuple)  |                           +-------------+
+-------------+

#3.2 gRPC Interface Definition

Core gRPC interfaces for PolicyEngineService:

PROTOBUF
syntax = "proto3";

package com.onto.control.policy;

service PolicyEngineService {
    // Evaluate access policy
    rpc EvaluatePolicy(PolicyEvaluationRequest)
        returns (PolicyEvaluationResponse);

    // Batch access check
    rpc BatchCheckAccess(BatchAccessCheckRequest)
        returns (BatchAccessCheckResponse);

    // Query rewrite (zero-intrusion data filtering)
    rpc RewriteQuery(QueryRewriteRequest)
        returns (QueryRewriteResponse);

    // Get effective permissions for a subject
    rpc GetEffectivePermissions(EffectivePermissionsRequest)
        returns (EffectivePermissionsResponse);
}

message PolicyEvaluationRequest {
    Subject subject = 1;           // Subject information
    string action = 2;             // Operation type
    Resource resource = 3;         // Resource information
    EnvironmentContext env = 4;    // Environment context
}

message PolicyEvaluationResponse {
    Decision decision = 1;         // ALLOW / DENY
    repeated Obligation obligations = 2;  // Additional obligations
    string reason = 3;             // Decision reason
    int64 evaluation_time_ms = 4;  // Evaluation time
}

message Subject {
    string id = 1;
    string type = 2;               // USER, SERVICE, GROUP
    map<string, string> attributes = 3;
    repeated string roles = 4;
}

message Resource {
    string id = 1;
    string type = 2;               // ONTOLOGY, DATASET, OBJECT, FIELD
    map<string, string> attributes = 3;
    string classification = 4;     // Data classification level
}

#4. Three-Layer Model Coordination

#4.1 Scenario 1: Data Analyst Viewing Customer Data

Consider the following scenario: a data analyst needs to view the phone number field in a customer dataset.

Code
Subject: analyst_001 (Role: DATA_ANALYST)
Action: READ
Resource: customer_dataset.phone_number (Classification: B2-Internal Sensitive)

Evaluation Process:
---------------------------------------------------------
[RBAC] DATA_ANALYST role has READ permission?   -> ALLOW
[ABAC] Is it currently work hours?              -> ALLOW (09:00-18:00)
[ABAC] Classification B2 <= User clearance B3?  -> ALLOW
[ABAC] Is request from intranet?                -> ALLOW (10.0.x.x)
[ReBAC] Is user a member of the dataset's project? -> ALLOW

Final Decision: ALLOW
Obligations: Apply PARTIAL_MASK to phone_number field
---------------------------------------------------------

#4.2 Scenario 2: External Partner Viewing Sales Report

Code
Subject: partner_vendor_01 (Role: EXTERNAL_PARTNER)
Action: READ
Resource: sales_report_2024 (Classification: B1-Internal General)

Evaluation Process:
---------------------------------------------------------
[RBAC] EXTERNAL_PARTNER role has READ permission?  -> ALLOW (limited)
[ABAC] Is it within contract validity period?      -> ALLOW
[ABAC] Classification B1 <= External visible A2?   -> DENY !!!
[ReBAC] Does external partner have collaboration?  -> ALLOW

Final Decision: DENY (ABAC layer denied, DENY-overrides)
Reason: Data classification level exceeds external partner clearance
---------------------------------------------------------

#4.3 Scenario 3: Project Manager Cross-Project Access

Code
Subject: pm_zhang (Role: PROJECT_MANAGER)
Action: READ
Resource: project_alpha/model_config (Classification: C1-Confidential)

Evaluation Process:
---------------------------------------------------------
[RBAC] PROJECT_MANAGER role has READ permission?   -> ALLOW
[ABAC] C1 confidential data requires special approval? -> NOT_APPLICABLE
[ReBAC] Is pm_zhang a member of project_alpha?     -> Check graph...
        pm_zhang -> member_of -> project_beta  (is beta member)
        pm_zhang -> member_of -> project_alpha (NOT alpha member)
        => DENY

Final Decision: DENY (ReBAC layer denied)
Reason: Subject is not a member of the target project
---------------------------------------------------------

#5. Performance Optimization

#5.1 Multi-Level Cache Architecture

Permission evaluation is a high-frequency operation. coomia-dip employs multi-level caching:

Code
+-------------------+     +-------------------+     +-------------------+
|   L1: Local Cache |     |   L2: Redis       |     |   L3: Database    |
|   (Caffeine)      |     |   (Cluster)       |     |   (PostgreSQL)    |
|                   |     |                   |     |                   |
|  TTL: 30s         |     |  TTL: 5min        |     |  Persistent       |
|  Capacity: 10K    |     |  Capacity: 100K   |     |  Storage          |
|  Hit Rate: ~85%   |     |  Hit Rate: ~12%   |     |  Hit Rate: ~3%    |
+-------------------+     +-------------------+     +-------------------+
         |                        |                         |
         +------------------------+-------------------------+
                              |
                     Invalidation Strategy:
                     - Role change -> Clear subject cache
                     - Policy change -> Clear all policy cache
                     - Relation change -> Clear relation path cache

#5.2 RBAC Fast Path

For pure RBAC scenarios (no ABAC/ReBAC required), PolicyEngineService provides a fast path optimization:

Java
public PolicyDecision evaluateFastPath(Subject subject, String action,
                                        Resource resource) {
    // Fast path: direct RBAC cache lookup
    Set<Permission> permissions = rbacCache.getPermissions(subject.getRoles());
    for (Permission perm : permissions) {
        if (perm.matches(action, resource.getType())) {
            // Check if ABAC/ReBAC evaluation needed
            if (!perm.hasConditions() && !perm.requiresRelationCheck()) {
                return PolicyDecision.ALLOW;  // Fast allow
            }
        }
    }
    // Fallback to full evaluation
    return evaluateFullPath(subject, action, resource);
}

The fast path completes evaluation in < 1ms, covering approximately 70% of requests.

#5.3 Performance Benchmarks

ScenarioAvg LatencyP99 LatencyThroughput
RBAC fast path0.3ms1.2ms50K QPS
RBAC + ABAC2.1ms8.5ms15K QPS
RBAC + ABAC + ReBAC5.8ms22ms5K QPS
Query rewrite3.2ms15ms10K QPS
Batch check (100 resources)12ms45ms2K QPS

#6. Integration with Other Services

#6.1 Integration Architecture

Code
+-------------------+     +-------------------+
| API Gateway       |---->| PolicyEngine      |
| (59 REST endpoints)|     | Service           |
+-------------------+     +---+-----+-----+---+
                            |     |     |
              +-------------+     |     +-------------+
              |                   |                   |
              v                   v                   v
+-------------------+  +-------------------+  +-------------------+
| Classification    |  | AuditService      |  | DataMask          |
| Service           |  | (13 event types)  |  | Service           |
| (7-tier)          |  | (3 Kafka topics)  |  | (6 masking modes) |
+-------------------+  +-------------------+  +-------------------+

#6.2 Audit Integration

Every policy evaluation generates an audit event:

Java
AuditEvent policyAudit = AuditEvent.builder()
    .eventType(AuditEventType.POLICY_EVALUATION)
    .subject(request.getSubject().getId())
    .action(request.getAction())
    .resource(request.getResource().getId())
    .decision(response.getDecision().name())
    .reason(response.getReason())
    .evaluationTimeMs(response.getEvaluationTimeMs())
    .timestamp(Instant.now())
    .build();

auditService.publishAsync(policyAudit);  // Async publish to Kafka

#6.3 SDK Integration

The Python SDK provides a concise permission check interface through the OntoPlatform facade:

Python
from ontology_sdk import OntoPlatform

platform = OntoPlatform(endpoint="grpc://control-Layer:9090")

# Check access permission
result = await platform.policy.check_access(
    subject_id="analyst_001",
    action="READ",
    resource_id="customer_dataset",
    resource_type="DATASET"
)

if result.allowed:
    data = await platform.ontology.query("Customer", limit=100)
    # Data is automatically masked (based on policy obligations)
else:
    print(f"Access denied: {result.reason}")

#7. Policy Management and Governance

#7.1 Policy Lifecycle

Code
+--------+     +---------+     +--------+     +--------+
| Draft  |---->| Pending |---->| Active |---->| Archived|
| DRAFT  |     | PENDING |     | ACTIVE |     | ARCHIVED|
+--------+     +---------+     +--------+     +--------+
    ^                              |
    |                              v
    +------- Needs Changes <-- +-----------+
                               | Deprecated|
                               | DEPRECATED|
                               +-----------+

#7.2 Policy Version Control

All policy changes go through version control with rollback support:

YAML
policy:
  id: "POL-DATASET-READ-001"
  version: 3
  name: "Dataset Read Policy"
  description: "Controls read access to datasets"
  status: ACTIVE
  effective_from: "2026-01-01T00:00:00Z"
  rules:
    - effect: ALLOW
      subjects:
        roles: [DATA_ANALYST, DATA_ENGINEER]
      actions: [READ, EXPORT]
      resources:
        types: [DATASET]
      conditions:
        - attribute: "resource.classification"
          operator: "lt"
          value: "C1"
        - attribute: "environment.time"
          operator: "between"
          value: ["09:00", "18:00"]
      obligations:
        - type: MASK
          params:
            fields: ["phone", "email", "id_card"]
            mode: PARTIAL_MASK

#7.3 Policy Conflict Detection

When a new policy may conflict with existing policies, the system automatically detects and alerts:

Code
New Policy: "Allow DATA_ANALYST to read all DATASETs"
Existing Policy: "Deny anyone from reading DATASETs with classification >= C1"

Conflict Detection Result:
  Type: POTENTIAL_CONFLICT
  Impact: Datasets with classification >= C1
  Recommendation: Add classification < C1 condition to new policy
  Current Behavior: DENY-overrides guarantees safety (existing policy wins)

#8. Production Deployment Recommendations

#8.1 High-Availability Deployment

Code
                     +-------------------+
                     |   Load Balancer   |
                     +-------------------+
                        |      |      |
              +---------+      |      +---------+
              |                |                |
    +---------v-----+ +-------v-------+ +------v--------+
    | PolicyEngine  | | PolicyEngine  | | PolicyEngine  |
    | Instance 1    | | Instance 2    | | Instance 3    |
    +---------------+ +---------------+ +---------------+
              |                |                |
              +-------+--------+--------+-------+
                      |                 |
              +-------v-------+ +------v--------+
              |   Redis       | |  PostgreSQL   |
              |   Cluster     | |  (Primary +   |
              |   (3 nodes)   | |   2 Replicas) |
              +---------------+ +---------------+

#8.2 Monitoring Metrics

MetricThresholdAlert Level
Policy eval latency P99> 50msWARNING
Policy eval latency P99> 200msCRITICAL
Cache hit rate< 70%WARNING
Policy eval DENY ratio> 30%INFO
Policy change frequency> 10/minWARNING

#8.3 Capacity Planning

Code
Estimation Formula:
  QPS = Active Users x Avg Operations/min x Evaluations/Operation

Example:
  1000 Active Users x 10 Ops/min x 2 Evals/Op = 333 QPS

Recommended Configuration:
  < 500 QPS:  2 instances, 2 CPU, 4GB RAM
  < 2000 QPS: 3 instances, 4 CPU, 8GB RAM
  < 10000 QPS: 5 instances, 8 CPU, 16GB RAM

#9. Comparison with Mainstream Solutions

Featurecoomia-dipOpen Policy AgentCasbinKeycloak
RBACNativeRequires policy writingNativeNative
ABACNativeNativeLimitedLimited
ReBACNativeCustom requiredNot supportedNot supported
Query rewriteNativeNot supportedNot supportedNot supported
Data masking6 modesNot supportedNot supportedNot supported
Data classification7-tierNot supportedNot supportedNot supported
gRPC integrationNativeNeeds adapterEmbeddedREST
Audit trail13 event typesDecision logsNoneLimited

#10. Future Evolution

#10.1 Near-Term Roadmap

  • Policy as Code: Git-managed policy versions with CI/CD auto-deployment
  • Policy Simulation: Test policy change impacts without affecting production
  • Cross-Platform Federated Permissions: Support permission federation across multiple coomia-dip instances

#10.2 Long-Term Vision

  • AI-Driven Policy Recommendations: Automatically recommend permission policies based on access patterns
  • Zero Trust Network Integration: Deep integration with Service Mesh (Istio)
  • Compliance Automation: Automatic generation of MLPS Level 3 / GDPR compliance reports

#Key Takeaways

  1. Three-layer complementarity: RBAC handles coarse-grained role control, ABAC handles attribute-conditional refinement, ReBAC handles relationship graph authorization -- together they cover all enterprise authorization scenarios
  2. DENY-overrides: Security-first policy combination semantics where any layer's denial is final
  3. Fast path optimization: 70% of requests take the RBAC fast path with latency < 1ms
  4. Zero-intrusion query rewriting: Business code is unaware of permission logic; queries are automatically rewritten based on policies
  5. Complete audit trail: Every policy evaluation generates audit events ensuring compliance traceability
  6. Palantir parity: Open-source implementation equivalent to Foundry's Multipass + Marking + Project membership capabilities

#Next Article

The next article S6-02: RBAC Implementation: Modeling Roles, Permissions, and Resources will dive deep into the complete RBAC layer implementation, including role inheritance, permission models, resource hierarchies, and integration with Spring Security.

Tags: #PermissionModel #RBAC #ABAC #ReBAC #PolicyEngine #AccessControl #coomia-dip #PlatformEngineering #SecurityArchitecture #Palantir