test(iam): add policy_is_allowed

This commit is contained in:
bestgopher
2024-12-23 21:46:25 +08:00
parent efed0a4884
commit 2126c36a73
20 changed files with 1454 additions and 212 deletions
+46 -11
View File
@@ -1,23 +1,34 @@
use super::func::InnerFunc;
use serde::de::{Error, IgnoredAny, SeqAccess};
use serde::{de, Deserialize, Deserializer, Serialize};
use std::{collections::HashMap, fmt};
pub type BoolFunc = InnerFunc<BoolFuncValue>;
impl BoolFunc {
pub fn evaluate_bool(&self, values: &HashMap<String, Vec<String>>) -> bool {
match values.get(self.key.name().as_str()).and_then(|x| x.get(0)) {
Some(x) => self.values.0.to_string().as_str() == x,
None => false,
for inner in self.0.iter() {
if !match values.get(inner.key.name().as_str()).and_then(|x| x.get(0)) {
Some(x) => inner.values.0.to_string().as_str() == x,
None => false,
} {
return false;
}
}
true
}
pub fn evaluate_null(&self, values: &HashMap<String, Vec<String>>) -> bool {
let len = values.get(self.key.name().as_str()).map(Vec::len).unwrap_or(0);
if self.values.0 {
return len == 0;
for inner in self.0.iter() {
let len = values.get(inner.key.name().as_str()).map(Vec::len).unwrap_or(0);
let r = if inner.values.0 { len == 0 } else { len != 0 };
if !r {
return false;
}
}
len != 0
true
}
}
@@ -50,17 +61,32 @@ impl<'de> Deserialize<'de> for BoolFuncValue {
fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
where
E: de::Error,
E: Error,
{
Ok(BoolFuncValue(value))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
E: Error,
{
Ok(BoolFuncValue(value.parse::<bool>().map_err(|e| E::custom(format!("{e:?}")))?))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let Some(v) = seq.next_element::<BoolFuncValue>()? else {
return Err(Error::custom("no value for boolean"));
};
if seq.next_element::<IgnoredAny>()?.is_some() {
return Err(Error::custom("only allow one boolean value"));
}
Ok(v)
}
}
deserializer.deserialize_any(BoolOrStringVisitor)
@@ -70,6 +96,7 @@ impl<'de> Deserialize<'de> for BoolFuncValue {
#[cfg(test)]
mod tests {
use super::{BoolFunc, BoolFuncValue};
use crate::policy::function::func::FuncKeyValue;
use crate::policy::function::{
key::Key,
key_name::AwsKeyName::*,
@@ -79,8 +106,10 @@ mod tests {
fn new_func(name: KeyName, variable: Option<String>, value: bool) -> BoolFunc {
BoolFunc {
key: Key { name, variable },
values: BoolFuncValue(value),
0: vec![FuncKeyValue {
key: Key { name, variable },
values: BoolFuncValue(value),
}],
}
}
@@ -92,6 +121,8 @@ mod tests {
#[test_case(r#"{"aws:SecureTransport/a": "false"}"#, new_func(Aws(AWSSecureTransport), Some("a".into()), false); "10")]
#[test_case(r#"{"aws:SecureTransport/a": true}"#, new_func(Aws(AWSSecureTransport), Some("a".into()), true); "11")]
#[test_case(r#"{"aws:SecureTransport/a": false}"#, new_func(Aws(AWSSecureTransport), Some("a".into()), false); "12")]
#[test_case(r#"{"aws:SecureTransport/a": [true]}"#, new_func(Aws(AWSSecureTransport), Some("a".into()), true); "13")]
#[test_case(r#"{"aws:SecureTransport/a": ["false"]}"#, new_func(Aws(AWSSecureTransport), Some("a".into()), false); "14")]
fn test_deser(input: &str, expect: BoolFunc) -> Result<(), serde_json::Error> {
let v: BoolFunc = serde_json::from_str(input)?;
assert_eq!(v, expect);
@@ -103,6 +134,9 @@ mod tests {
#[test_case(r#"{"aws:usernamea/value":"johndoe"}"#)]
#[test_case(r#"{"aws:usernamea/value":["johndoe", "aaa"]}"#)]
#[test_case(r#""aaa""#)]
#[test_case(r#"{"aws:SecureTransport/a": ["false", "true"]}"#)]
#[test_case(r#"{"aws:SecureTransport/a": [true, false]}"#)]
#[test_case(r#"{"aws:SecureTransport/a": ["aa"]}"#)]
fn test_deser_failed(input: &str) {
assert!(serde_json::from_str::<BoolFunc>(input).is_err());
}
@@ -111,6 +145,7 @@ mod tests {
#[test_case(r#"{"aws:SecureTransport":"false"}"#, new_func(Aws(AWSSecureTransport), None, false);"2")]
#[test_case(r#"{"aws:SecureTransport/aa":"true"}"#, new_func(Aws(AWSSecureTransport),Some("aa".into()), true);"3")]
#[test_case(r#"{"aws:SecureTransport/aa":"false"}"#, new_func(Aws(AWSSecureTransport), Some("aa".into()), false);"4")]
# [test_case(r#"{"aws:SecureTransport/aa":"false"}"#, new_func(Aws(AWSSecureTransport), Some("aa".into()), false); "5")]
fn test_ser(expect: &str, input: BoolFunc) -> Result<(), serde_json::Error> {
let v = serde_json::to_string(&input)?;
assert_eq!(v.as_str(), expect);