cf-authz-resolver-sdk 0.2.3

SDK for authz_resolver module: evaluation API, constraints, PEP compiler
Documentation

AuthZ Resolver SDK

SDK crate for the AuthZ Resolver module, providing the authorization evaluation API, constraint model, and PEP (Policy Enforcement Point) helpers for CyberFabric.

Overview

This crate defines the transport-agnostic interface for the AuthZ Resolver module:

  • AuthZResolverClient — Async trait for evaluating authorization requests
  • AuthZResolverPluginClient — Async trait for PDP plugin implementations
  • PolicyEnforcer — High-level PEP helper (build request → evaluate → compile to AccessScope)
  • EvaluationRequest / EvaluationResponse — AuthZEN 1.0-based request/response models
  • Constraint typesConstraint, Predicate, EqPredicate, InPredicate
  • PEP compilercompile_to_access_scope() converts PDP constraints to SecureORM AccessScope

Usage

PolicyEnforcer (Recommended)

The PolicyEnforcer encapsulates the full PEP flow — most services should use this:

use authz_resolver_sdk::pep::{PolicyEnforcer, ResourceType};
use modkit_security::pep_properties;

// Define resource type with supported constraint properties
const USER: ResourceType = ResourceType {
    name: "gts.x.core.users.user.v1~",
    supported_properties: &[pep_properties::OWNER_TENANT_ID, pep_properties::RESOURCE_ID],
};

// Create enforcer once during service init
let authz = hub.get::<dyn AuthZResolverClient>()?;
let enforcer = PolicyEnforcer::new(authz.clone());

// All CRUD operations return AccessScope for SecureORM
let scope = enforcer.access_scope(&ctx, &USER, "list", None).await?;
let scope = enforcer.access_scope(&ctx, &USER, "get", Some(resource_id)).await?;
let scope = enforcer.access_scope(&ctx, &USER, "create", None).await?;

Advanced: AccessRequest Overrides

For non-default scenarios (cross-tenant, barrier bypass, ABAC properties):

use authz_resolver_sdk::pep::AccessRequest;
use authz_resolver_sdk::models::TenantMode;

let scope = enforcer.access_scope_with(
    &ctx, &USER, "create", None,
    &AccessRequest::new()
        .context_tenant_id(target_tenant_id)
        .tenant_mode(TenantMode::RootOnly)
        .resource_property(pep_properties::OWNER_TENANT_ID, target_tenant_id),
).await?;

Low-Level: Direct Evaluation

For cases where PolicyEnforcer is not suitable:

use authz_resolver_sdk::{AuthZResolverClient, EvaluationRequest};

let authz = hub.get::<dyn AuthZResolverClient>()?;
let response = authz.evaluate(request).await?;

if response.decision {
    // Access granted; optionally compile constraints
    let scope = compile_to_access_scope(&response, true, supported_properties)?;
} else {
    // Access denied
    let reason = response.context.deny_reason;
}

Models

EvaluationRequest (AuthZEN 1.0)

pub struct EvaluationRequest {
    pub subject: Subject,                  // Who (id, type, properties)
    pub action: Action,                    // What (name: "list", "get", "create", ...)
    pub resource: Resource,                // On what (type, id, properties)
    pub context: EvaluationRequestContext, // Tenant context, token scopes, capabilities
}

EvaluationResponse

pub struct EvaluationResponse {
    pub decision: bool,                      // Allow or deny
    pub context: EvaluationResponseContext,   // Constraints or deny reason
}

Constraints

PDP returns row-level constraints when decision=true:

pub struct Constraint {
    pub predicates: Vec<Predicate>,  // ANDed within a constraint
}
// Multiple constraints are ORed

pub enum Predicate {
    Eq(EqPredicate),   // property = value
    In(InPredicate),   // property IN (values)
}

PEP Compilation Matrix

require_constraints constraints Result
false empty AccessScope::allow_all()
false present Compile to AccessScope
true empty Error (fail-closed)
true present Compile to AccessScope

Unknown properties fail that constraint (fail-closed). If ALL constraints fail, access is denied.

Error Handling

use authz_resolver_sdk::pep::enforcer::EnforcerError;

match enforcer.access_scope(&ctx, &USER, "get", Some(id)).await {
    Ok(scope) => { /* use with SecureORM */ },
    Err(EnforcerError::Denied { deny_reason }) => { /* PDP denied access */ },
    Err(EnforcerError::EvaluationFailed(e)) => { /* PDP call failed */ },
    Err(EnforcerError::CompileFailed(e)) => { /* constraint compilation failed */ },
}

Implementing a Plugin

Implement AuthZResolverPluginClient and register with a GTS instance ID:

use async_trait::async_trait;
use authz_resolver_sdk::{
    AuthZResolverPluginClient, EvaluationRequest, EvaluationResponse, AuthZResolverError,
};

struct MyPdpPlugin { /* ... */ }

#[async_trait]
impl AuthZResolverPluginClient for MyPdpPlugin {
    async fn evaluate(&self, request: EvaluationRequest)
        -> Result<EvaluationResponse, AuthZResolverError> {
        // Evaluate policies, return decision + constraints
    }
}

License

Apache-2.0