mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat(rbac)!: add Azure RBAC engine, FFI API, and cross-language tests (#577)
- add Azure RBAC condition interpreter and builtin evaluation in core (expressions, parser updates, evaluator, and test harness) - introduce comprehensive RBAC YAML test suites and coverage for i - action/suboperation - strings - numbers - bools - IP - GUID - dates - times - lists - quantifiers (ForAnyOfAnyValues, ForAllOfAllValues) - expose RBAC evaluation through FFI with an `rbac` feature flag enabled by default - add C# `RbacEngine` wrapper + P/Invoke entrypoint and document usage in C# README - expand C# tests to execute all RBAC YAML cases with per-case logging - wire test assets into C# test output and centralize YAML dependency versions Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
8814eda0ae
commit
47cc27ff49
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use alloc::format;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::languages::azure_rbac::ast::ArrayExpression;
|
||||
use crate::value::Value;
|
||||
|
||||
use super::error::ConditionEvalError;
|
||||
use super::eval::Evaluator;
|
||||
|
||||
impl<'a> Evaluator<'a> {
|
||||
pub(super) fn eval_array_expression(
|
||||
&mut self,
|
||||
array: &ArrayExpression,
|
||||
) -> Result<Value, ConditionEvalError> {
|
||||
let collection = self.evaluate_value(&array.array)?;
|
||||
let values: Vec<&Value> = match collection {
|
||||
Value::Array(ref list) => list.iter().collect(),
|
||||
Value::Set(ref set) => set.iter().collect(),
|
||||
Value::Undefined => return Ok(Value::Bool(false)),
|
||||
_ => {
|
||||
return Err(ConditionEvalError::new(
|
||||
"Array expression expects a list or set",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let is_any = array.operator.name.eq_ignore_ascii_case("ANY");
|
||||
let is_all = array.operator.name.eq_ignore_ascii_case("ALL");
|
||||
if !is_any && !is_all {
|
||||
return Err(ConditionEvalError::new(format!(
|
||||
"Unsupported array operator: {}",
|
||||
array.operator.name
|
||||
)));
|
||||
}
|
||||
|
||||
let variable = array.variable.as_deref();
|
||||
if is_any {
|
||||
for value in &values {
|
||||
let matched = self.eval_array_condition(variable, value, &array.condition)?;
|
||||
if matched {
|
||||
return Ok(Value::Bool(true));
|
||||
}
|
||||
}
|
||||
return Ok(Value::Bool(false));
|
||||
}
|
||||
|
||||
let mut saw_value = false;
|
||||
for value in &values {
|
||||
saw_value = true;
|
||||
let matched = self.eval_array_condition(variable, value, &array.condition)?;
|
||||
if !matched {
|
||||
return Ok(Value::Bool(false));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Bool(!saw_value || is_all))
|
||||
}
|
||||
|
||||
fn eval_array_condition(
|
||||
&mut self,
|
||||
variable: Option<&str>,
|
||||
value: &Value,
|
||||
condition: &crate::languages::azure_rbac::ast::ConditionExpr,
|
||||
) -> Result<bool, ConditionEvalError> {
|
||||
if let Some(name) = variable {
|
||||
self.push_variable(name, value.clone());
|
||||
let result = self.evaluate_bool(condition);
|
||||
self.pop_variable();
|
||||
result
|
||||
} else {
|
||||
self.evaluate_bool(condition)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user