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>
65 lines
2.0 KiB
Rust
65 lines
2.0 KiB
Rust
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
use crate::value::Value;
|
|
use alloc::string::ToString as _;
|
|
|
|
use super::common;
|
|
use super::evaluator::RbacBuiltinError;
|
|
|
|
#[cfg(feature = "time")]
|
|
use chrono::DateTime;
|
|
|
|
// Compare RFC3339 timestamps using the requested operator.
|
|
//
|
|
// Interesting examples:
|
|
// - left: @Request[date] = "2023-05-01T12:00:00Z",
|
|
// right: @Environment[utcNow] = "2023-05-01T11:59:59Z",
|
|
// op: ">" => true
|
|
// - left: @Resource[expiry] = "2024-01-01T00:00:00Z",
|
|
// right: @Environment[utcNow] = "2024-01-01T00:00:00Z",
|
|
// op: "==" => true
|
|
// - left: @Request[scheduled] = "2023-12-31T23:59:59-08:00",
|
|
// right: @Environment[utcNow] = "2024-01-01T07:59:59Z",
|
|
// op: "==" => true (same instant, different offsets)
|
|
pub(super) fn datetime_compare(
|
|
left: &Value,
|
|
right: &Value,
|
|
op: &str,
|
|
name: &'static str,
|
|
) -> Result<bool, RbacBuiltinError> {
|
|
// Parse both operands as RFC3339 strings.
|
|
let lhs = common::value_as_string(left, name)?;
|
|
let rhs = common::value_as_string(right, name)?;
|
|
|
|
#[cfg(feature = "time")]
|
|
{
|
|
// Compare instants using chrono's RFC3339 parsing.
|
|
let left_dt = DateTime::parse_from_rfc3339(&lhs)
|
|
.map_err(|err| RbacBuiltinError::new(err.to_string()))?;
|
|
let right_dt = DateTime::parse_from_rfc3339(&rhs)
|
|
.map_err(|err| RbacBuiltinError::new(err.to_string()))?;
|
|
Ok(match op {
|
|
"==" => left_dt == right_dt,
|
|
"<" => left_dt < right_dt,
|
|
"<=" => left_dt <= right_dt,
|
|
">" => left_dt > right_dt,
|
|
">=" => left_dt >= right_dt,
|
|
_ => false,
|
|
})
|
|
}
|
|
|
|
#[cfg(not(feature = "time"))]
|
|
{
|
|
// Without the time feature, compare lexicographically as strings.
|
|
Ok(match op {
|
|
"==" => lhs == rhs,
|
|
"<" => lhs < rhs,
|
|
"<=" => lhs <= rhs,
|
|
">" => lhs > rhs,
|
|
">=" => lhs >= rhs,
|
|
_ => false,
|
|
})
|
|
}
|
|
}
|