mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
- 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>
78 lines
2.4 KiB
Rust
78 lines
2.4 KiB
Rust
// 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)
|
|
}
|
|
}
|
|
}
|