rewrite iam

This commit is contained in:
weisd
2025-01-14 22:03:45 +08:00
parent 821ff036be
commit b29b15f3b5
50 changed files with 4529 additions and 1657 deletions
+3 -4
View File
@@ -27,9 +27,8 @@ impl AddrFunc {
}
}
#[derive(Serialize, Clone)]
#[derive(Serialize, Clone, PartialEq, Eq, Debug)]
#[serde(transparent)]
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
pub struct AddrFuncValue(Vec<IpNetwork>);
impl<'de> Deserialize<'de> for AddrFuncValue {
@@ -73,9 +72,9 @@ impl<'de> Deserialize<'de> for AddrFuncValue {
cidr_str.to_mut().push_str("/32");
}
Ok(cidr_str
cidr_str
.parse::<IpNetwork>()
.map_err(|_| E::custom(format!("{v} can not be parsed to CIDR")))?)
.map_err(|_| E::custom(format!("{v} can not be parsed to CIDR")))
}
}
+9 -1
View File
@@ -1,3 +1,5 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use super::func::InnerFunc;
@@ -5,6 +7,12 @@ use super::func::InnerFunc;
pub type BinaryFunc = InnerFunc<BinaryFuncValue>;
// todo implement it
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(transparent)]
pub struct BinaryFuncValue(String);
impl BinaryFunc {
pub fn evaluate(&self, _values: &HashMap<String, Vec<String>>) -> bool {
todo!()
}
}
+2 -3
View File
@@ -7,7 +7,7 @@ pub type BoolFunc = InnerFunc<BoolFuncValue>;
impl BoolFunc {
pub fn evaluate_bool(&self, values: &HashMap<String, Vec<String>>) -> bool {
for inner in self.0.iter() {
if !match values.get(inner.key.name().as_str()).and_then(|x| x.get(0)) {
if !match values.get(inner.key.name().as_str()).and_then(|x| x.first()) {
Some(x) => inner.values.0.to_string().as_str() == x,
None => false,
} {
@@ -32,8 +32,7 @@ impl BoolFunc {
}
}
#[derive(Clone)]
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct BoolFuncValue(bool);
impl Serialize for BoolFuncValue {
+35 -3
View File
@@ -1,12 +1,12 @@
use serde::de::{Error, MapAccess};
use serde::ser::SerializeMap;
use serde::{Deserialize, Serialize, Serializer};
use serde::Deserialize;
use std::collections::HashMap;
use time::OffsetDateTime;
use super::{addr::AddrFunc, binary::BinaryFunc, bool_null::BoolFunc, date::DateFunc, number::NumberFunc, string::StringFunc};
#[derive(Clone, Deserialize)]
#[derive(Clone, Deserialize, Debug)]
pub enum Condition {
StringEquals(StringFunc),
StringNotEquals(StringFunc),
@@ -102,7 +102,7 @@ impl Condition {
StringNotEqualsIgnoreCase(s) => s.evaluate(for_all, true, false, true, values),
StringLike(s) => s.evaluate(for_all, false, true, false, values),
StringNotLike(s) => s.evaluate(for_all, false, true, true, values),
BinaryEquals(s) => todo!(),
BinaryEquals(s) => s.evaluate(values),
IpAddress(s) => s.evaluate(values),
NotIpAddress(s) => s.evaluate(values),
Null(s) => s.evaluate_null(values),
@@ -164,3 +164,35 @@ impl Condition {
}
}
}
impl PartialEq for Condition {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::StringEquals(l0), Self::StringEquals(r0)) => l0 == r0,
(Self::StringNotEquals(l0), Self::StringNotEquals(r0)) => l0 == r0,
(Self::StringEqualsIgnoreCase(l0), Self::StringEqualsIgnoreCase(r0)) => l0 == r0,
(Self::StringNotEqualsIgnoreCase(l0), Self::StringNotEqualsIgnoreCase(r0)) => l0 == r0,
(Self::StringLike(l0), Self::StringLike(r0)) => l0 == r0,
(Self::StringNotLike(l0), Self::StringNotLike(r0)) => l0 == r0,
(Self::BinaryEquals(l0), Self::BinaryEquals(r0)) => l0 == r0,
(Self::IpAddress(l0), Self::IpAddress(r0)) => l0 == r0,
(Self::NotIpAddress(l0), Self::NotIpAddress(r0)) => l0 == r0,
(Self::Null(l0), Self::Null(r0)) => l0 == r0,
(Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
(Self::NumericEquals(l0), Self::NumericEquals(r0)) => l0 == r0,
(Self::NumericNotEquals(l0), Self::NumericNotEquals(r0)) => l0 == r0,
(Self::NumericLessThan(l0), Self::NumericLessThan(r0)) => l0 == r0,
(Self::NumericLessThanEquals(l0), Self::NumericLessThanEquals(r0)) => l0 == r0,
(Self::NumericGreaterThan(l0), Self::NumericGreaterThan(r0)) => l0 == r0,
(Self::NumericGreaterThanIfExists(l0), Self::NumericGreaterThanIfExists(r0)) => l0 == r0,
(Self::NumericGreaterThanEquals(l0), Self::NumericGreaterThanEquals(r0)) => l0 == r0,
(Self::DateEquals(l0), Self::DateEquals(r0)) => l0 == r0,
(Self::DateNotEquals(l0), Self::DateNotEquals(r0)) => l0 == r0,
(Self::DateLessThan(l0), Self::DateLessThan(r0)) => l0 == r0,
(Self::DateLessThanEquals(l0), Self::DateLessThanEquals(r0)) => l0 == r0,
(Self::DateGreaterThan(l0), Self::DateGreaterThan(r0)) => l0 == r0,
(Self::DateGreaterThanEquals(l0), Self::DateGreaterThanEquals(r0)) => l0 == r0,
_ => false,
}
}
}
+3 -4
View File
@@ -8,7 +8,7 @@ pub type DateFunc = InnerFunc<DateFuncValue>;
impl DateFunc {
pub fn evaluate(&self, op: impl Fn(&OffsetDateTime, &OffsetDateTime) -> bool, values: &HashMap<String, Vec<String>>) -> bool {
for inner in self.0.iter() {
let v = match values.get(inner.key.name().as_str()).and_then(|x| x.get(0)) {
let v = match values.get(inner.key.name().as_str()).and_then(|x| x.first()) {
Some(x) => x,
None => return false,
};
@@ -26,8 +26,7 @@ impl DateFunc {
}
}
#[derive(Clone)]
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct DateFuncValue(OffsetDateTime);
impl Serialize for DateFuncValue {
@@ -52,7 +51,7 @@ impl<'de> Deserialize<'de> for DateFuncValue {
{
struct DateVisitor;
impl<'de> de::Visitor<'de> for DateVisitor {
impl de::Visitor<'_> for DateVisitor {
type Value = DateFuncValue;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+2 -2
View File
@@ -7,10 +7,10 @@ use serde::{
use super::key::Key;
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(PartialEq, Eq, Debug)]
pub struct InnerFunc<T>(pub(crate) Vec<FuncKeyValue<T>>);
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(PartialEq, Eq, Debug)]
pub struct FuncKeyValue<T> {
pub key: Key,
pub values: T,
+8 -6
View File
@@ -1,9 +1,9 @@
use super::key_name::KeyName;
use crate::policy::{Error, Validator};
use crate::{policy::Error as PolicyError, sys::Validator};
use ecstore::error::Error;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(PartialEq, Eq))]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(into = "String")]
#[serde(try_from = "&str")]
pub struct Key {
@@ -11,7 +11,9 @@ pub struct Key {
pub variable: Option<String>,
}
impl Validator for Key {}
impl Validator for Key {
type Error = Error;
}
impl Key {
pub fn is(&self, other: &KeyName) -> bool {
@@ -36,7 +38,7 @@ impl From<Key> for String {
let mut data = String::from(Into::<&str>::into(&value.name));
if let Some(x) = value.variable.as_ref() {
data.push('/');
data.push_str(&x);
data.push_str(x);
}
data
}
@@ -47,7 +49,7 @@ impl TryFrom<&str> for Key {
fn try_from(value: &str) -> Result<Self, Self::Error> {
let mut iter = value.splitn(2, '/');
let name = iter.next().ok_or_else(|| Error::InvalidKey(value.to_string()))?;
let name = iter.next().ok_or_else(|| PolicyError::InvalidKey(value.to_string()))?;
let variable = iter.next().map(Into::into);
Ok(Self {
+9 -9
View File
@@ -54,9 +54,9 @@ impl KeyName {
KeyName::Aws(AwsKeyName::AWSUsername),
KeyName::Aws(AwsKeyName::AWSGroups),
// ldap
KeyName::Ldap(LdapKeyName::LDAPUser),
KeyName::Ldap(LdapKeyName::LDAPUsername),
KeyName::Ldap(LdapKeyName::LDAPGroups),
KeyName::Ldap(LdapKeyName::User),
KeyName::Ldap(LdapKeyName::Username),
KeyName::Ldap(LdapKeyName::Groups),
// jwt
KeyName::Jwt(JwtKeyName::JWTSub),
KeyName::Jwt(JwtKeyName::JWTIss),
@@ -252,13 +252,13 @@ pub enum SvcKeyName {
#[serde(try_from = "&str", into = "&str")]
pub enum LdapKeyName {
#[strum(serialize = "ldap:user")]
LDAPUser,
User,
#[strum(serialize = "ldap:username")]
LDAPUsername,
Username,
#[strum(serialize = "ldap:groups")]
LDAPGroups,
Groups,
}
#[derive(Clone, EnumString, Debug, IntoStaticStr, Eq, PartialEq, Serialize, Deserialize)]
@@ -312,7 +312,7 @@ mod tests {
#[test_case("s3:x-amz-copy-source", KeyName::S3(S3KeyName::S3XAmzCopySource))]
#[test_case("aws:SecureTransport", KeyName::Aws(AwsKeyName::AWSSecureTransport))]
#[test_case("jwt:sub", KeyName::Jwt(JwtKeyName::JWTSub))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::LDAPUser))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::User))]
#[test_case("sts:DurationSeconds", KeyName::Sts(StsKeyName::STSDurationSeconds))]
#[test_case("svc:DurationSeconds", KeyName::Svc(SvcKeyName::SVCDurationSeconds))]
fn key_name_from_str_successful(val: &str, except: KeyName) {
@@ -332,7 +332,7 @@ mod tests {
#[test_case("s3:x-amz-copy-source", KeyName::S3(S3KeyName::S3XAmzCopySource))]
#[test_case("aws:SecureTransport", KeyName::Aws(AwsKeyName::AWSSecureTransport))]
#[test_case("jwt:sub", KeyName::Jwt(JwtKeyName::JWTSub))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::LDAPUser))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::User))]
#[test_case("sts:DurationSeconds", KeyName::Sts(StsKeyName::STSDurationSeconds))]
#[test_case("svc:DurationSeconds", KeyName::Svc(SvcKeyName::SVCDurationSeconds))]
fn key_name_deserialize(val: &str, except: KeyName) {
@@ -349,7 +349,7 @@ mod tests {
#[test_case("s3:x-amz-copy-source", KeyName::S3(S3KeyName::S3XAmzCopySource))]
#[test_case("aws:SecureTransport", KeyName::Aws(AwsKeyName::AWSSecureTransport))]
#[test_case("jwt:sub", KeyName::Jwt(JwtKeyName::JWTSub))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::LDAPUser))]
#[test_case("ldap:user", KeyName::Ldap(LdapKeyName::User))]
#[test_case("sts:DurationSeconds", KeyName::Sts(StsKeyName::STSDurationSeconds))]
#[test_case("svc:DurationSeconds", KeyName::Svc(SvcKeyName::SVCDurationSeconds))]
fn key_name_serialize(except: &str, value: KeyName) {
+3 -4
View File
@@ -8,14 +8,13 @@ use serde::{
pub type NumberFunc = InnerFunc<NumberFuncValue>;
#[derive(Clone)]
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumberFuncValue(i64);
impl NumberFunc {
pub fn evaluate(&self, op: impl Fn(&i64, &i64) -> bool, if_exists: bool, values: &HashMap<String, Vec<String>>) -> bool {
for inner in self.0.iter() {
let v = match values.get(inner.key.name().as_str()).and_then(|x| x.get(0)) {
let v = match values.get(inner.key.name().as_str()).and_then(|x| x.first()) {
Some(x) => x,
None => return if_exists,
};
@@ -49,7 +48,7 @@ impl<'de> Deserialize<'de> for NumberFuncValue {
{
struct NumberVisitor;
impl<'de> Visitor<'de> for NumberVisitor {
impl Visitor<'_> for NumberVisitor {
type Value = NumberFuncValue;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+4 -4
View File
@@ -63,7 +63,7 @@ impl FuncKeyValue<StringFuncValue> {
.map(|c| {
let mut c = Cow::from(c);
for key in KeyName::COMMON_KEYS {
match values.get(key.name()).and_then(|x| x.get(0)) {
match values.get(key.name()).and_then(|x| x.first()) {
Some(v) if !v.is_empty() => return Cow::Owned(c.to_mut().replace(&key.var_name(), v)),
_ => continue,
};
@@ -93,7 +93,7 @@ impl FuncKeyValue<StringFuncValue> {
.map(|c| {
let mut c = Cow::from(c);
for key in KeyName::COMMON_KEYS {
match values.get(key.name()).and_then(|x| x.get(0)) {
match values.get(key.name()).and_then(|x| x.first()) {
Some(v) if !v.is_empty() => return Cow::Owned(c.to_mut().replace(&key.var_name(), v)),
_ => continue,
};
@@ -118,8 +118,8 @@ impl FuncKeyValue<StringFuncValue> {
}
/// 解析values字段
#[derive(Clone)]
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StringFuncValue(pub Set<String>);
impl Serialize for StringFuncValue {