Add comprehensive documentation and GitHub Copilot configuration: - docs/knowledge/: 17 deep-dive knowledge files covering value semantics, RVM architecture, builtins, FFI boundary, feature composition, error handling migration, policy evaluation security, Rego semantics, interpreter/compiler architecture, Azure Policy/RBAC, engine API, time builtins, language extension guide, tooling architecture, causality/partial eval, Rego compiler, Azure Policy aliases, and telemetry/diagnostics - .github/agents/: 16 role-specific AI agent definitions (red-teamer, semantics-expert, architect, performance-engineer, test-engineer, verification-engineer, security-auditor, reliability-engineer, support-engineer, ci-engineer, refactorer, api-steward, program-manager, demo-engineer, dx-engineer, tech-lead) - .github/skills/: 6 workflow skill definitions (thorough-review, design-alternatives, add-builtin, opa-conformance, security-review, verification) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: anakrish <35780660+anakrish@users.noreply.github.com>
5.6 KiB
Knowledge: Azure RBAC Language
Deep knowledge about the Azure RBAC condition language extension in
src/languages/azure_rbac/. Read this before modifying RBAC evaluation.
How RBAC Differs from Rego and Azure Policy
| Aspect | Azure RBAC | Azure Policy | Rego |
|---|---|---|---|
| Purpose | Access control conditions | Resource compliance | General policy |
| Execution | Direct interpretation | RVM compilation | RVM or interpreter |
| Syntax | Condition expression strings | JSON constraints | Rego source |
| Logic | AND/OR/NOT + quantifiers | allOf/anyOf/not | Rules + comprehensions |
| Builtins | 40+ ABAC functions | 19 operators | 100+ OPA builtins |
Key difference: RBAC uses direct interpretation (no RVM compilation).
It has its own ConditionInterpreter that evaluates condition strings directly.
Directory Structure
src/languages/azure_rbac/
mod.rs Module root
interpreter.rs Direct evaluation engine (66 lines)
ast/ Expression types (8 files)
expr.rs ConditionExpr enum — 15+ variants
context.rs EvaluationContext (Principal, Resource, Request, Environment)
operators.rs Operator definitions
literals.rs Literal types (string, number, bool, datetime, time, set, list)
references.rs Attribute references
spans.rs Source location tracking
parser/ Condition string → AST (3 files)
builtins/ 40+ ABAC condition functions (14 files)
test_cases/ 40+ YAML test files
Evaluation Context
RBAC evaluation happens against a rich context:
struct EvaluationContext {
principal: Principal, // Who is accessing
resource: Resource, // What is being accessed
request: RequestContext, // What action is requested
environment: EnvironmentContext, // When/where (time, network)
action: Option<String>, // Control-plane action
suboperation: Option<String>, // Sub-operation identifier
}
struct Principal {
id: String,
principal_type: PrincipalType, // User, Group, ServicePrincipal, MSI
custom_security_attributes: Value,
}
struct Resource {
id: String,
resource_type: String,
scope: String,
attributes: Value,
}
Expression Types
The RBAC AST represents condition expressions:
enum ConditionExpr {
Logical(LogicalExpression), // AND/OR
Unary(UnaryExpression), // NOT, exists, notExists
Binary(BinaryExpression), // Operator comparisons
FunctionCall(FunctionCallExpression), // ToLower, Substring, etc.
AttributeReference(AttributeReference), // principal.id, resource.attributes.env
ArrayExpression(ArrayExpression), // ANY/ALL quantifiers
Identifier(IdentifierExpression),
VariableReference(VariableReference), // Loop variables
PropertyAccess(PropertyAccessExpression),
// Literals: String, Number, Bool, Null, DateTime, Time, Set, List
}
Condition Interpreter
The interpreter evaluates conditions directly (no compilation step):
struct ConditionInterpreter<'a> {
context: &'a EvaluationContext,
}
impl ConditionInterpreter {
fn evaluate_str(&self, condition: &str) -> Result<bool>
fn evaluate_condition_expression(&self, cond: &ConditionExpression) -> Result<bool>
fn evaluate_bool(&self, expr: &ConditionExpr) -> Result<bool>
fn evaluate_value(&self, expr: &ConditionExpr) -> Result<Value>
}
Evaluation Flow
- Parse condition string →
ConditionExpressionwithConditionExprAST - Recursively evaluate:
- Logical: AND/OR with short-circuit evaluation
- Unary: NOT, exists (check if attribute is present), notExists
- Binary: delegate to
RbacBuiltinEvaluatorfor comparison - Function calls: evaluate with built-in RBAC functions
- Array expressions: ANY/ALL quantifiers over collections
- Attribute references: resolve from evaluation context
RBAC Builtins (40+ functions)
Organized by category:
| Category | Functions |
|---|---|
| Strings | StringEquals, StringEqualsIgnoreCase, StringLike, StringMatches, StringNotEquals, ... |
| Numbers | NumericEquals, NumericGreaterThan, NumericInRange, ... |
| Booleans | BoolEquals, BoolNotEquals |
| GUIDs | GuidEquals, GuidNotEquals |
| DateTime | DateTimeEquals, DateTimeGreaterThan, DateTimeInRange, ... |
| Time of Day | TimeOfDayEquals, TimeOfDayGreaterThan, TimeOfDayInRange, ... |
| IP | IpMatch, IpNotMatch, IpInRange |
| Lists | ListContains, ListNotContains, NormalizeList, NormalizeSet |
| Actions | ActionMatches, SubOperationMatches |
| Quantifiers | ANY, ALL, EXISTS |
Each builtin is an enum variant in RbacBuiltin used for direct dispatch
in BinaryExpression evaluation.
Key Invariants
-
No RVM backend — RBAC is pure interpretation. Changes to the RVM do not affect RBAC evaluation.
-
Short-circuit evaluation — AND/OR evaluate left-to-right and stop early. This is semantically important (not just an optimization).
-
Attribute resolution — attributes are resolved from the evaluation context at evaluation time. Missing attributes may produce errors or false depending on the operator.
-
Case sensitivity — string comparisons have both case-sensitive and case-insensitive variants. Use the correct one.
Testing
40+ YAML test files in test_cases/ provide comprehensive coverage.
Each test case specifies a condition string, evaluation context, and
expected result.