Skip to main content

rskit_authz/engine/
model.rs

1//! RBAC + ABAC policy model: subjects, resources, requests, roles, permissions, and conditions.
2
3use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8/// Request, subject, or resource attributes.
9pub type Attributes = HashMap<String, Value>;
10
11/// The authenticated caller.
12#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
13pub struct Subject {
14    /// Subject identifier.
15    pub id: String,
16    /// RBAC role bindings.
17    pub roles: Vec<String>,
18    /// Additional subject attributes for ABAC evaluation.
19    pub attributes: Attributes,
20}
21
22/// The target being accessed.
23#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
24pub struct Resource {
25    /// Resource type or namespace.
26    pub resource_type: String,
27    /// Resource identifier.
28    pub id: String,
29    /// Additional resource attributes for ABAC evaluation.
30    pub attributes: Attributes,
31}
32
33/// Canonical authorization request.
34#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
35pub struct Request {
36    /// Subject performing the action.
37    pub subject: Subject,
38    /// Resource being accessed.
39    pub resource: Resource,
40    /// Requested action.
41    pub action: String,
42    /// Request-scoped attributes.
43    pub context: Attributes,
44}
45
46/// RBAC permission with wildcard matching.
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
48pub struct Permission {
49    /// Resource pattern.
50    pub resource: String,
51    /// Action pattern.
52    pub action: String,
53    /// Attribute conditions that must hold for this permission grant.
54    #[serde(default)]
55    pub conditions: Vec<Condition>,
56}
57
58impl Permission {
59    /// Return `true` when this permission matches the supplied resource/action shape.
60    #[must_use]
61    pub fn matches(&self, resource: &str, action: &str) -> bool {
62        crate::matcher::match_pattern(&self.resource, resource)
63            && crate::matcher::match_pattern(&self.action, action)
64    }
65}
66
67/// RBAC role definition with optional inheritance.
68#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
69pub struct Role {
70    /// Role name.
71    pub name: String,
72    /// Parent roles inherited transitively.
73    pub inherits: Vec<String>,
74    /// Granted permissions.
75    pub permissions: Vec<Permission>,
76}
77
78/// Result of a matched policy.
79#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
80#[serde(rename_all = "snake_case")]
81#[non_exhaustive]
82pub enum Effect {
83    /// Allow the request.
84    Allow,
85    /// Deny the request.
86    #[default]
87    Deny,
88}
89
90/// Source of an attribute used by a condition.
91#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
92#[serde(rename_all = "snake_case")]
93#[non_exhaustive]
94pub enum AttributeSource {
95    /// Read from subject attributes.
96    #[default]
97    Subject,
98    /// Read from resource attributes.
99    Resource,
100    /// Read from request context.
101    Context,
102}
103
104/// Comparison operator for ABAC conditions.
105#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
106#[serde(rename_all = "snake_case")]
107#[non_exhaustive]
108pub enum Operator {
109    /// Exact equality.
110    #[default]
111    Equals,
112    /// Exact inequality.
113    NotEquals,
114    /// Membership in a value list.
115    OneOf,
116}
117
118/// ABAC condition evaluated against request attributes.
119#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
120pub struct Condition {
121    /// Attribute source.
122    pub source: AttributeSource,
123    /// Attribute key to read.
124    pub key: String,
125    /// Comparison operator.
126    pub operator: Operator,
127    /// Literal values to compare against.
128    pub values: Vec<Value>,
129    /// Optional attribute source for cross-field comparisons.
130    pub compare_source: Option<AttributeSource>,
131    /// Optional attribute key for cross-field comparisons.
132    pub compare_key: Option<String>,
133}
134
135/// ABAC policy rule.
136#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
137pub struct Policy {
138    /// Policy name.
139    pub name: String,
140    /// Policy effect.
141    pub effect: Effect,
142    /// Action patterns.
143    pub actions: Vec<String>,
144    /// Resource patterns.
145    pub resources: Vec<String>,
146    /// Attribute conditions.
147    pub conditions: Vec<Condition>,
148}
149
150/// Final authorization decision.
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub struct Decision {
153    /// Whether the request is allowed.
154    pub allowed: bool,
155    /// Human-readable reason.
156    pub reason: String,
157}