From ab31be8d460ba16b23e89f4aa8b47861bc774394 Mon Sep 17 00:00:00 2001 From: weisd Date: Wed, 26 Mar 2025 11:39:14 +0800 Subject: [PATCH] ecstore update bucket policy --- Cargo.lock | 1 + ecstore/Cargo.toml | 1 + ecstore/src/bucket/metadata.rs | 2 +- ecstore/src/bucket/metadata_sys.rs | 2 +- ecstore/src/bucket/mod.rs | 1 - ecstore/src/bucket/policy/action.rs | 605 ------------------ ecstore/src/bucket/policy/bucket_policy.rs | 259 -------- .../src/bucket/policy/condition/function.rs | 304 --------- ecstore/src/bucket/policy/condition/key.rs | 155 ----- .../src/bucket/policy/condition/keyname.rs | 475 -------------- ecstore/src/bucket/policy/condition/mod.rs | 4 - ecstore/src/bucket/policy/condition/name.rs | 75 --- ecstore/src/bucket/policy/effect.rs | 40 -- ecstore/src/bucket/policy/mod.rs | 103 --- ecstore/src/bucket/policy/principal.rs | 25 - ecstore/src/bucket/policy/resource.rs | 263 -------- ecstore/src/bucket/policy_sys.rs | 11 +- 17 files changed, 8 insertions(+), 2318 deletions(-) delete mode 100644 ecstore/src/bucket/policy/action.rs delete mode 100644 ecstore/src/bucket/policy/bucket_policy.rs delete mode 100644 ecstore/src/bucket/policy/condition/function.rs delete mode 100644 ecstore/src/bucket/policy/condition/key.rs delete mode 100644 ecstore/src/bucket/policy/condition/keyname.rs delete mode 100644 ecstore/src/bucket/policy/condition/mod.rs delete mode 100644 ecstore/src/bucket/policy/condition/name.rs delete mode 100644 ecstore/src/bucket/policy/effect.rs delete mode 100644 ecstore/src/bucket/policy/mod.rs delete mode 100644 ecstore/src/bucket/policy/principal.rs delete mode 100644 ecstore/src/bucket/policy/resource.rs diff --git a/Cargo.lock b/Cargo.lock index b309799a..37c39134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1920,6 +1920,7 @@ dependencies = [ "path-absolutize", "path-clean", "pin-project-lite", + "policy", "protos", "rand 0.8.5", "reed-solomon-erasure", diff --git a/ecstore/Cargo.toml b/ecstore/Cargo.toml index f7357e91..4f822c03 100644 --- a/ecstore/Cargo.toml +++ b/ecstore/Cargo.toml @@ -16,6 +16,7 @@ backon.workspace = true blake2 = "0.10.6" bytes.workspace = true common.workspace = true +policy.workspace = true chrono.workspace = true glob = "0.3.2" thiserror.workspace = true diff --git a/ecstore/src/bucket/metadata.rs b/ecstore/src/bucket/metadata.rs index 92019725..135bbb78 100644 --- a/ecstore/src/bucket/metadata.rs +++ b/ecstore/src/bucket/metadata.rs @@ -1,9 +1,9 @@ -use super::policy::bucket_policy::BucketPolicy; use super::{quota::BucketQuota, target::BucketTargets}; use super::object_lock::ObjectLockApi; use super::versioning::VersioningApi; use byteorder::{BigEndian, ByteOrder, LittleEndian}; +use policy::policy::BucketPolicy; use rmp_serde::Serializer as rmpSerializer; use s3s::dto::{ BucketLifecycleConfiguration, NotificationConfiguration, ObjectLockConfiguration, ReplicationConfiguration, diff --git a/ecstore/src/bucket/metadata_sys.rs b/ecstore/src/bucket/metadata_sys.rs index be43ed03..9d18700b 100644 --- a/ecstore/src/bucket/metadata_sys.rs +++ b/ecstore/src/bucket/metadata_sys.rs @@ -13,6 +13,7 @@ use crate::store::ECStore; use crate::utils::xml::deserialize; use common::error::{Error, Result}; use futures::future::join_all; +use policy::policy::BucketPolicy; use s3s::dto::{ BucketLifecycleConfiguration, NotificationConfiguration, ObjectLockConfiguration, ReplicationConfiguration, ServerSideEncryptionConfiguration, Tagging, VersioningConfiguration, @@ -22,7 +23,6 @@ use tokio::sync::RwLock; use tracing::{error, warn}; use super::metadata::{load_bucket_metadata, BucketMetadata}; -use super::policy::bucket_policy::BucketPolicy; use super::quota::BucketQuota; use super::target::BucketTargets; diff --git a/ecstore/src/bucket/mod.rs b/ecstore/src/bucket/mod.rs index fb9f0230..33e5b87e 100644 --- a/ecstore/src/bucket/mod.rs +++ b/ecstore/src/bucket/mod.rs @@ -2,7 +2,6 @@ pub mod error; pub mod metadata; pub mod metadata_sys; pub mod object_lock; -pub mod policy; pub mod policy_sys; mod quota; pub mod tagging; diff --git a/ecstore/src/bucket/policy/action.rs b/ecstore/src/bucket/policy/action.rs deleted file mode 100644 index d444e52d..00000000 --- a/ecstore/src/bucket/policy/action.rs +++ /dev/null @@ -1,605 +0,0 @@ -use crate::{bucket::policy::condition::keyname::ALL_SUPPORT_KEYS, utils}; -use lazy_static::lazy_static; -use serde::{Deserialize, Serialize}; -use std::{ - collections::{HashMap, HashSet}, - str::FromStr, - vec, -}; - -use super::condition::{ - key::{Key, KeySet}, - keyname::{KeyName, COMMOM_KEYS}, -}; - -#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] - -pub struct ActionSet(pub HashSet); - -impl ActionSet { - pub fn is_match(&self, act: &Action) -> bool { - for item in self.0.iter() { - if item.is_match(act) { - return true; - } - - if item == &Action::GetObjectVersion && act == &Action::GetObjectVersion { - return true; - } - } - - false - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl AsRef> for ActionSet { - fn as_ref(&self) -> &HashSet { - &self.0 - } -} - -// TODO:: 使用字符串 -// 定义Action枚举类型 -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Default, Hash)] -pub enum Action { - #[serde(rename = "s3:AbortMultipartUpload")] - AbortMultipartUpload, - #[serde(rename = "s3:CreateBucket")] - CreateBucket, - #[serde(rename = "s3:DeleteBucket")] - DeleteBucket, - #[serde(rename = "s3:ForceDeleteBucket")] - ForceDeleteBucket, - #[serde(rename = "s3:DeleteBucketPolicy")] - DeleteBucketPolicy, - #[serde(rename = "s3:DeleteBucketCors")] - DeleteBucketCors, - #[serde(rename = "s3:DeleteObject")] - DeleteObject, - #[serde(rename = "s3:GetBucketLocation")] - GetBucketLocation, - #[serde(rename = "s3:GetBucketNotification")] - GetBucketNotification, - #[serde(rename = "s3:GetBucketPolicy")] - GetBucketPolicy, - #[serde(rename = "s3:GetBucketCors")] - GetBucketCors, - #[serde(rename = "s3:GetObject")] - GetObject, - #[serde(rename = "s3:GetObjectAttributes")] - GetObjectAttributes, - #[serde(rename = "s3:HeadBucket")] - HeadBucket, - #[serde(rename = "s3:ListAllMyBuckets")] - ListAllMyBuckets, - #[serde(rename = "s3:ListBucket")] - ListBucket, - #[serde(rename = "s3:GetBucketPolicyStatus")] - GetBucketPolicyStatus, - #[serde(rename = "s3:ListBucketVersions")] - ListBucketVersions, - #[serde(rename = "s3:ListBucketMultipartUploads")] - ListBucketMultipartUploads, - #[serde(rename = "s3:ListenNotification")] - ListenNotification, - #[serde(rename = "s3:ListenBucketNotification")] - ListenBucketNotification, - #[serde(rename = "s3:ListMultipartUploadParts")] - ListMultipartUploadParts, - #[serde(rename = "s3:PutLifecycleConfiguration")] - PutLifecycleConfiguration, - #[serde(rename = "s3:GetLifecycleConfiguration")] - GetLifecycleConfiguration, - #[serde(rename = "s3:PutBucketNotification")] - PutBucketNotification, - #[serde(rename = "s3:PutBucketPolicy")] - PutBucketPolicy, - #[serde(rename = "s3:PutBucketCors")] - PutBucketCors, - #[serde(rename = "s3:PutObject")] - PutObject, - #[serde(rename = "s3:DeleteObjectVersion")] - DeleteObjectVersion, - #[serde(rename = "s3:DeleteObjectVersionTagging")] - DeleteObjectVersionTagging, - #[serde(rename = "s3:GetObjectVersion")] - GetObjectVersion, - #[serde(rename = "s3:GetObjectVersionAttributes")] - GetObjectVersionAttributes, - #[serde(rename = "s3:GetObjectVersionTagging")] - GetObjectVersionTagging, - #[serde(rename = "s3:PutObjectVersionTagging")] - PutObjectVersionTagging, - #[serde(rename = "s3:BypassGovernanceRetention")] - BypassGovernanceRetention, - #[serde(rename = "s3:PutObjectRetention")] - PutObjectRetention, - #[serde(rename = "s3:GetObjectRetention")] - GetObjectRetention, - #[serde(rename = "s3:GetObjectLegalHold")] - GetObjectLegalHold, - #[serde(rename = "s3:PutObjectLegalHold")] - PutObjectLegalHold, - #[serde(rename = "s3:GetBucketObjectLockConfiguration")] - GetBucketObjectLockConfiguration, - #[serde(rename = "s3:PutBucketObjectLockConfiguration")] - PutBucketObjectLockConfiguration, - #[serde(rename = "s3:GetBucketTagging")] - GetBucketTagging, - #[serde(rename = "s3:PutBucketTagging")] - PutBucketTagging, - #[serde(rename = "s3:GetObjectTagging")] - GetObjectTagging, - #[serde(rename = "s3:PutObjectTagging")] - PutObjectTagging, - #[serde(rename = "s3:DeleteObjectTagging")] - DeleteObjectTagging, - #[serde(rename = "s3:PutBucketEncryption")] - PutBucketEncryption, - #[serde(rename = "s3:GetBucketEncryption")] - GetBucketEncryption, - #[serde(rename = "s3:PutBucketVersioning")] - PutBucketVersioning, - #[serde(rename = "s3:GetBucketVersioning")] - GetBucketVersioning, - #[serde(rename = "s3:PutReplicationConfiguration")] - PutReplicationConfiguration, - #[serde(rename = "s3:GetReplicationConfiguration")] - GetReplicationConfiguration, - #[serde(rename = "s3:ReplicateObject")] - ReplicateObject, - #[serde(rename = "s3:ReplicateDelete")] - ReplicateDelete, - #[serde(rename = "s3:ReplicateTags")] - ReplicateTags, - #[serde(rename = "s3:GetObjectVersionForReplication")] - GetObjectVersionForReplication, - #[serde(rename = "s3:RestoreObject")] - RestoreObject, - #[serde(rename = "s3:ResetBucketReplicationState")] - ResetBucketReplicationState, - #[serde(rename = "s3:PutObjectFanOut")] - PutObjectFanOut, - #[default] - #[serde(rename = "s3:*")] - AllActions, -} - -lazy_static! { - #[derive(Debug)] - static ref SUPPORT_OBJCET_ACTIONS: HashSet = { - let mut h = HashSet::new(); - h.insert(Action::AllActions); - h.insert(Action::AbortMultipartUpload); - h.insert(Action::DeleteObject); - h.insert(Action::GetObject); - h.insert(Action::ListMultipartUploadParts); - h.insert(Action::PutObject); - h.insert(Action::BypassGovernanceRetention); - h.insert(Action::PutObjectRetention); - h.insert(Action::GetObjectRetention); - h.insert(Action::PutObjectLegalHold); - h.insert(Action::GetObjectLegalHold); - h.insert(Action::GetObjectTagging); - h.insert(Action::PutObjectTagging); - h.insert(Action::DeleteObjectTagging); - h.insert(Action::GetObjectVersion); - h.insert(Action::GetObjectVersionTagging); - h.insert(Action::DeleteObjectVersion); - h.insert(Action::DeleteObjectVersionTagging); - h.insert(Action::PutObjectVersionTagging); - h.insert(Action::ReplicateObject); - h.insert(Action::ReplicateDelete); - h.insert(Action::ReplicateTags); - h.insert(Action::GetObjectVersionForReplication); - h.insert(Action::RestoreObject); - h.insert(Action::ResetBucketReplicationState); - h.insert(Action::PutObjectFanOut); - h.insert(Action::GetObjectAttributes); - h.insert(Action::GetObjectVersionAttributes); - h - }; -} - -impl Action { - pub fn is_object_action(&self) -> bool { - for act in SUPPORT_OBJCET_ACTIONS.iter() { - if self.is_match(act) { - return true; - } - } - false - } - pub fn is_match(&self, a: &Action) -> bool { - utils::wildcard::match_pattern(self.clone().as_str(), a.clone().as_str()) - } - - fn as_str(&self) -> &'static str { - match self { - Action::AbortMultipartUpload => "s3:AbortMultipartUpload", - Action::CreateBucket => "s3:CreateBucket", - Action::DeleteBucket => "s3:DeleteBucket", - Action::ForceDeleteBucket => "s3:ForceDeleteBucket", - Action::DeleteBucketPolicy => "s3:DeleteBucketPolicy", - Action::DeleteBucketCors => "s3:DeleteBucketCors", - Action::DeleteObject => "s3:DeleteObject", - Action::GetBucketLocation => "s3:GetBucketLocation", - Action::GetBucketNotification => "s3:GetBucketNotification", - Action::GetBucketPolicy => "s3:GetBucketPolicy", - Action::GetBucketCors => "s3:GetBucketCors", - Action::GetObject => "s3:GetObject", - Action::GetObjectAttributes => "s3:GetObjectAttributes", - Action::HeadBucket => "s3:HeadBucket", - Action::ListAllMyBuckets => "s3:ListAllMyBuckets", - Action::ListBucket => "s3:ListBucket", - Action::GetBucketPolicyStatus => "s3:GetBucketPolicyStatus", - Action::ListBucketVersions => "s3:ListBucketVersions", - Action::ListBucketMultipartUploads => "s3:ListBucketMultipartUploads", - Action::ListenNotification => "s3:ListenNotification", - Action::ListenBucketNotification => "s3:ListenBucketNotification", - Action::ListMultipartUploadParts => "s3:ListMultipartUploadParts", - Action::PutLifecycleConfiguration => "s3:PutLifecycleConfiguration", - Action::GetLifecycleConfiguration => "s3:GetLifecycleConfiguration", - Action::PutBucketNotification => "s3:PutBucketNotification", - Action::PutBucketPolicy => "s3:PutBucketPolicy", - Action::PutBucketCors => "s3:PutBucketCors", - Action::PutObject => "s3:PutObject", - Action::DeleteObjectVersion => "s3:DeleteObjectVersion", - Action::DeleteObjectVersionTagging => "s3:DeleteObjectVersionTagging", - Action::GetObjectVersion => "s3:GetObjectVersion", - Action::GetObjectVersionAttributes => "s3:GetObjectVersionAttributes", - Action::GetObjectVersionTagging => "s3:GetObjectVersionTagging", - Action::PutObjectVersionTagging => "s3:PutObjectVersionTagging", - Action::BypassGovernanceRetention => "s3:BypassGovernanceRetention", - Action::PutObjectRetention => "s3:PutObjectRetention", - Action::GetObjectRetention => "s3:GetObjectRetention", - Action::GetObjectLegalHold => "s3:GetObjectLegalHold", - Action::PutObjectLegalHold => "s3:PutObjectLegalHold", - Action::GetBucketObjectLockConfiguration => "s3:GetBucketObjectLockConfiguration", - Action::PutBucketObjectLockConfiguration => "s3:PutBucketObjectLockConfiguration", - Action::GetBucketTagging => "s3:GetBucketTagging", - Action::PutBucketTagging => "s3:PutBucketTagging", - Action::GetObjectTagging => "s3:GetObjectTagging", - Action::PutObjectTagging => "s3:PutObjectTagging", - Action::DeleteObjectTagging => "s3:DeleteObjectTagging", - Action::PutBucketEncryption => "s3:PutEncryptionConfiguration", - Action::GetBucketEncryption => "s3:GetEncryptionConfiguration", - Action::PutBucketVersioning => "s3:PutBucketVersioning", - Action::GetBucketVersioning => "s3:GetBucketVersioning", - Action::PutReplicationConfiguration => "s3:GetReplicationConfiguration", - Action::GetReplicationConfiguration => "s3:PutReplicationConfiguration", - Action::ReplicateObject => "s3:ReplicateObject", - Action::ReplicateDelete => "s3:ReplicateDelete", - Action::ReplicateTags => "s3:ReplicateTags", - Action::GetObjectVersionForReplication => "s3:GetObjectVersionForReplication", - Action::RestoreObject => "s3:RestoreObject", - Action::ResetBucketReplicationState => "s3:ResetBucketReplicationState", - Action::PutObjectFanOut => "s3:PutObjectFanOut", - Action::AllActions => "s3:*", - } - } - - // pub fn from_str(s: &str) -> Option { - // match s { - // "s3:AbortMultipartUpload" => Some(Action::AbortMultipartUpload), - // "s3:CreateBucket" => Some(Action::CreateBucket), - // "s3:DeleteBucket" => Some(Action::DeleteBucket), - // "s3:ForceDeleteBucket" => Some(Action::ForceDeleteBucket), - // "s3:DeleteBucketPolicy" => Some(Action::DeleteBucketPolicy), - // "s3:DeleteBucketCors" => Some(Action::DeleteBucketCors), - // "s3:DeleteObject" => Some(Action::DeleteObject), - // "s3:GetBucketLocation" => Some(Action::GetBucketLocation), - // "s3:GetBucketNotification" => Some(Action::GetBucketNotification), - // "s3:GetBucketPolicy" => Some(Action::GetBucketPolicy), - // "s3:GetBucketCors" => Some(Action::GetBucketCors), - // "s3:GetObject" => Some(Action::GetObject), - // "s3:GetObjectAttributes" => Some(Action::GetObjectAttributes), - // "s3:HeadBucket" => Some(Action::HeadBucket), - // "s3:ListAllMyBuckets" => Some(Action::ListAllMyBuckets), - // "s3:ListBucket" => Some(Action::ListBucket), - // "s3:GetBucketPolicyStatus" => Some(Action::GetBucketPolicyStatus), - // "s3:ListBucketVersions" => Some(Action::ListBucketVersions), - // "s3:ListBucketMultipartUploads" => Some(Action::ListBucketMultipartUploads), - // "s3:ListenNotification" => Some(Action::ListenNotification), - // "s3:ListenBucketNotification" => Some(Action::ListenBucketNotification), - // "s3:ListMultipartUploadParts" => Some(Action::ListMultipartUploadParts), - // "s3:PutLifecycleConfiguration" => Some(Action::PutLifecycleConfiguration), - // "s3:GetLifecycleConfiguration" => Some(Action::GetLifecycleConfiguration), - // "s3:PutBucketNotification" => Some(Action::PutBucketNotification), - // "s3:PutBucketPolicy" => Some(Action::PutBucketPolicy), - // "s3:PutBucketCors" => Some(Action::PutBucketCors), - // "s3:PutObject" => Some(Action::PutObject), - // "s3:DeleteObjectVersion" => Some(Action::DeleteObjectVersion), - // "s3:DeleteObjectVersionTagging" => Some(Action::DeleteObjectVersionTagging), - // "s3:GetObjectVersion" => Some(Action::GetObjectVersion), - // "s3:GetObjectVersionAttributes" => Some(Action::GetObjectVersionAttributes), - // "s3:GetObjectVersionTagging" => Some(Action::GetObjectVersionTagging), - // "s3:PutObjectVersionTagging" => Some(Action::PutObjectVersionTagging), - // "s3:BypassGovernanceRetention" => Some(Action::BypassGovernanceRetention), - // "s3:PutObjectRetention" => Some(Action::PutObjectRetention), - // "s3:GetObjectRetention" => Some(Action::GetObjectRetention), - // "s3:GetObjectLegalHold" => Some(Action::GetObjectLegalHold), - // "s3:PutObjectLegalHold" => Some(Action::PutObjectLegalHold), - // "s3:GetBucketObjectLockConfiguration" => Some(Action::GetBucketObjectLockConfiguration), - // "s3:PutBucketObjectLockConfiguration" => Some(Action::PutBucketObjectLockConfiguration), - // "s3:GetBucketTagging" => Some(Action::GetBucketTagging), - // "s3:PutBucketTagging" => Some(Action::PutBucketTagging), - // "s3:GetObjectTagging" => Some(Action::GetObjectTagging), - // "s3:PutObjectTagging" => Some(Action::PutObjectTagging), - // "s3:DeleteObjectTagging" => Some(Action::DeleteObjectTagging), - // "s3:PutEncryptionConfiguration" => Some(Action::PutBucketEncryption), - // "s3:GetEncryptionConfiguration" => Some(Action::GetBucketEncryption), - // "s3:PutBucketVersioning" => Some(Action::PutBucketVersioning), - // "s3:GetBucketVersioning" => Some(Action::GetBucketVersioning), - // "s3:PutReplicationConfiguration" => Some(Action::PutReplicationConfiguration), - // "s3:GetReplicationConfiguration" => Some(Action::GetReplicationConfiguration), - // "s3:ReplicateObject" => Some(Action::ReplicateObject), - // "s3:ReplicateDelete" => Some(Action::ReplicateDelete), - // "s3:ReplicateTags" => Some(Action::ReplicateTags), - // "s3:GetObjectVersionForReplication" => Some(Action::GetObjectVersionForReplication), - // "s3:RestoreObject" => Some(Action::RestoreObject), - // "s3:ResetBucketReplicationState" => Some(Action::ResetBucketReplicationState), - // "s3:PutObjectFanOut" => Some(Action::PutObjectFanOut), - // "s3:*" => Some(Action::AllActions), - // _ => None, - // } - // } -} - -impl FromStr for Action { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "s3:AbortMultipartUpload" => Ok(Action::AbortMultipartUpload), - "s3:CreateBucket" => Ok(Action::CreateBucket), - "s3:DeleteBucket" => Ok(Action::DeleteBucket), - "s3:ForceDeleteBucket" => Ok(Action::ForceDeleteBucket), - "s3:DeleteBucketPolicy" => Ok(Action::DeleteBucketPolicy), - "s3:DeleteBucketCors" => Ok(Action::DeleteBucketCors), - "s3:DeleteObject" => Ok(Action::DeleteObject), - "s3:GetBucketLocation" => Ok(Action::GetBucketLocation), - "s3:GetBucketNotification" => Ok(Action::GetBucketNotification), - "s3:GetBucketPolicy" => Ok(Action::GetBucketPolicy), - "s3:GetBucketCors" => Ok(Action::GetBucketCors), - "s3:GetObject" => Ok(Action::GetObject), - "s3:GetObjectAttributes" => Ok(Action::GetObjectAttributes), - "s3:HeadBucket" => Ok(Action::HeadBucket), - "s3:ListAllMyBuckets" => Ok(Action::ListAllMyBuckets), - "s3:ListBucket" => Ok(Action::ListBucket), - "s3:GetBucketPolicyStatus" => Ok(Action::GetBucketPolicyStatus), - "s3:ListBucketVersions" => Ok(Action::ListBucketVersions), - "s3:ListBucketMultipartUploads" => Ok(Action::ListBucketMultipartUploads), - "s3:ListenNotification" => Ok(Action::ListenNotification), - "s3:ListenBucketNotification" => Ok(Action::ListenBucketNotification), - "s3:ListMultipartUploadParts" => Ok(Action::ListMultipartUploadParts), - "s3:PutLifecycleConfiguration" => Ok(Action::PutLifecycleConfiguration), - "s3:GetLifecycleConfiguration" => Ok(Action::GetLifecycleConfiguration), - "s3:PutBucketNotification" => Ok(Action::PutBucketNotification), - "s3:PutBucketPolicy" => Ok(Action::PutBucketPolicy), - "s3:PutBucketCors" => Ok(Action::PutBucketCors), - "s3:PutObject" => Ok(Action::PutObject), - "s3:DeleteObjectVersion" => Ok(Action::DeleteObjectVersion), - "s3:DeleteObjectVersionTagging" => Ok(Action::DeleteObjectVersionTagging), - "s3:GetObjectVersion" => Ok(Action::GetObjectVersion), - "s3:GetObjectVersionAttributes" => Ok(Action::GetObjectVersionAttributes), - "s3:GetObjectVersionTagging" => Ok(Action::GetObjectVersionTagging), - "s3:PutObjectVersionTagging" => Ok(Action::PutObjectVersionTagging), - "s3:BypassGovernanceRetention" => Ok(Action::BypassGovernanceRetention), - "s3:PutObjectRetention" => Ok(Action::PutObjectRetention), - "s3:GetObjectRetention" => Ok(Action::GetObjectRetention), - "s3:GetObjectLegalHold" => Ok(Action::GetObjectLegalHold), - "s3:PutObjectLegalHold" => Ok(Action::PutObjectLegalHold), - "s3:GetBucketObjectLockConfiguration" => Ok(Action::GetBucketObjectLockConfiguration), - "s3:PutBucketObjectLockConfiguration" => Ok(Action::PutBucketObjectLockConfiguration), - "s3:GetBucketTagging" => Ok(Action::GetBucketTagging), - "s3:PutBucketTagging" => Ok(Action::PutBucketTagging), - "s3:GetObjectTagging" => Ok(Action::GetObjectTagging), - "s3:PutObjectTagging" => Ok(Action::PutObjectTagging), - "s3:DeleteObjectTagging" => Ok(Action::DeleteObjectTagging), - "s3:PutEncryptionConfiguration" => Ok(Action::PutBucketEncryption), - "s3:GetEncryptionConfiguration" => Ok(Action::GetBucketEncryption), - "s3:PutBucketVersioning" => Ok(Action::PutBucketVersioning), - "s3:GetBucketVersioning" => Ok(Action::GetBucketVersioning), - "s3:PutReplicationConfiguration" => Ok(Action::PutReplicationConfiguration), - "s3:GetReplicationConfiguration" => Ok(Action::GetReplicationConfiguration), - "s3:ReplicateObject" => Ok(Action::ReplicateObject), - "s3:ReplicateDelete" => Ok(Action::ReplicateDelete), - "s3:ReplicateTags" => Ok(Action::ReplicateTags), - "s3:GetObjectVersionForReplication" => Ok(Action::GetObjectVersionForReplication), - "s3:RestoreObject" => Ok(Action::RestoreObject), - "s3:ResetBucketReplicationState" => Ok(Action::ResetBucketReplicationState), - "s3:PutObjectFanOut" => Ok(Action::PutObjectFanOut), - "s3:*" => Ok(Action::AllActions), - _ => Err(()), - } - } -} - -pub struct ActionConditionKeyMap(HashMap); - -impl ActionConditionKeyMap { - pub fn lookup(&self, action: &Action) -> KeySet { - let common_keys: Vec = COMMOM_KEYS.iter().map(|v| v.to_key()).collect(); - - let mut merged_keys = KeySet::from_keys(&common_keys); - - for (act, key) in self.0.iter() { - if action.is_match(act) { - merged_keys.merge(key); - } - } - - merged_keys - } -} - -lazy_static! { - pub static ref IAMActionConditionKeyMap: ActionConditionKeyMap = create_action_condition_key_map(); -} - -fn create_action_condition_key_map() -> ActionConditionKeyMap { - let common_keys: Vec = COMMOM_KEYS.iter().map(|v| v.to_key()).collect(); - let all_support_keys: Vec = ALL_SUPPORT_KEYS.iter().map(|v| v.to_key()).collect(); - - let mut map = HashMap::new(); - - map.insert(Action::AllActions, KeySet::from_keys(&all_support_keys)); - map.insert(Action::AbortMultipartUpload, KeySet::from_keys(&common_keys)); - map.insert(Action::CreateBucket, KeySet::from_keys(&common_keys)); - - let mut delete_obj_keys = common_keys.clone(); - delete_obj_keys.push(KeyName::S3VersionID.to_key()); - map.insert(Action::DeleteObject, KeySet::from_keys(&delete_obj_keys)); - - map.insert(Action::GetBucketLocation, KeySet::from_keys(&common_keys)); - map.insert(Action::GetBucketPolicyStatus, KeySet::from_keys(&common_keys)); - - let mut get_obj_keys = common_keys.clone(); - get_obj_keys.extend(vec![ - KeyName::S3XAmzServerSideEncryption.to_key(), - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm.to_key(), - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID.to_key(), - KeyName::S3VersionID.to_key(), - KeyName::ExistingObjectTag.to_key(), - ]); - map.insert(Action::DeleteObject, KeySet::from_keys(&get_obj_keys)); - - map.insert(Action::HeadBucket, KeySet::from_keys(&common_keys)); - - let mut get_obj_attr_keys = common_keys.clone(); - get_obj_attr_keys.push(KeyName::ExistingObjectTag.to_key()); - map.insert(Action::DeleteObject, KeySet::from_keys(&get_obj_attr_keys)); - - let mut get_obj_ver_attr_keys = common_keys.clone(); - get_obj_ver_attr_keys.extend(vec![KeyName::S3VersionID.to_key(), KeyName::ExistingObjectTag.to_key()]); - map.insert(Action::DeleteObject, KeySet::from_keys(&get_obj_ver_attr_keys)); - - map.insert(Action::ListAllMyBuckets, KeySet::from_keys(&common_keys)); - - let mut list_bucket_keys = common_keys.clone(); - list_bucket_keys.extend(vec![ - KeyName::S3Prefix.to_key(), - KeyName::S3Delimiter.to_key(), - KeyName::S3MaxKeys.to_key(), - ]); - map.insert(Action::ListBucket, KeySet::from_keys(&list_bucket_keys)); - map.insert(Action::ListBucketVersions, KeySet::from_keys(&list_bucket_keys)); - - map.insert(Action::ListBucketMultipartUploads, KeySet::from_keys(&common_keys)); - map.insert(Action::ListenNotification, KeySet::from_keys(&common_keys)); - map.insert(Action::ListenBucketNotification, KeySet::from_keys(&common_keys)); - map.insert(Action::ListMultipartUploadParts, KeySet::from_keys(&common_keys)); - - let mut put_obj_keys = common_keys.clone(); - put_obj_keys.extend(vec![ - KeyName::S3XAmzCopySource.to_key(), - KeyName::S3XAmzServerSideEncryption.to_key(), - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm.to_key(), - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID.to_key(), - KeyName::S3XAmzMetadataDirective.to_key(), - KeyName::S3XAmzStorageClass.to_key(), - KeyName::S3VersionID.to_key(), - KeyName::S3ObjectLockRetainUntilDate.to_key(), - KeyName::S3ObjectLockMode.to_key(), - KeyName::S3ObjectLockLegalHold.to_key(), - KeyName::RequestObjectTagKeys.to_key(), - KeyName::RequestObjectTag.to_key(), - ]); - map.insert(Action::PutObject, KeySet::from_keys(&put_obj_keys)); - - let mut put_obj_retention_keys = common_keys.clone(); - put_obj_retention_keys.extend(vec![ - KeyName::S3XAmzServerSideEncryption.to_key(), - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm.to_key(), - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID.to_key(), - KeyName::S3ObjectLockRemainingRetentionDays.to_key(), - KeyName::S3ObjectLockRetainUntilDate.to_key(), - KeyName::S3ObjectLockMode.to_key(), - KeyName::S3VersionID.to_key(), - ]); - map.insert(Action::PutObjectRetention, KeySet::from_keys(&put_obj_retention_keys)); - - let mut get_obj_retention_keys = common_keys.clone(); - get_obj_retention_keys.extend(vec![ - KeyName::S3XAmzServerSideEncryption.to_key(), - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm.to_key(), - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID.to_key(), - KeyName::S3VersionID.to_key(), - ]); - map.insert(Action::GetObjectRetention, KeySet::from_keys(&get_obj_retention_keys)); - - let mut put_obj_hold_keys = common_keys.clone(); - put_obj_hold_keys.extend(vec![ - KeyName::S3XAmzServerSideEncryption.to_key(), - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm.to_key(), - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID.to_key(), - KeyName::S3ObjectLockLegalHold.to_key(), - KeyName::S3VersionID.to_key(), - ]); - map.insert(Action::PutObjectLegalHold, KeySet::from_keys(&put_obj_hold_keys)); - - map.insert(Action::GetObjectLegalHold, KeySet::from_keys(&common_keys)); - - let mut bypass_governance_retention_keys = common_keys.clone(); - bypass_governance_retention_keys.extend(vec![ - KeyName::S3VersionID.to_key(), - KeyName::S3ObjectLockRemainingRetentionDays.to_key(), - KeyName::S3ObjectLockRetainUntilDate.to_key(), - KeyName::S3ObjectLockMode.to_key(), - KeyName::S3ObjectLockLegalHold.to_key(), - KeyName::RequestObjectTagKeys.to_key(), - KeyName::RequestObjectTag.to_key(), - ]); - map.insert(Action::BypassGovernanceRetention, KeySet::from_keys(&bypass_governance_retention_keys)); - - map.insert(Action::GetBucketObjectLockConfiguration, KeySet::from_keys(&common_keys)); - map.insert(Action::PutBucketObjectLockConfiguration, KeySet::from_keys(&common_keys)); - map.insert(Action::GetBucketTagging, KeySet::from_keys(&common_keys)); - - let mut put_bucket_tagging_keys = common_keys.clone(); - put_bucket_tagging_keys.extend(vec![KeyName::RequestObjectTagKeys.to_key(), KeyName::RequestObjectTag.to_key()]); - map.insert(Action::PutBucketTagging, KeySet::from_keys(&put_bucket_tagging_keys)); - - let mut put_object_tagging_keys = common_keys.clone(); - put_object_tagging_keys.extend(vec![ - KeyName::S3VersionID.to_key(), - KeyName::ExistingObjectTag.to_key(), - KeyName::RequestObjectTagKeys.to_key(), - KeyName::RequestObjectTag.to_key(), - ]); - map.insert(Action::PutObjectTagging, KeySet::from_keys(&put_object_tagging_keys)); - - let mut get_object_tagging_keys = common_keys.clone(); - get_object_tagging_keys.extend(vec![KeyName::S3VersionID.to_key(), KeyName::ExistingObjectTag.to_key()]); - map.insert(Action::GetObjectTagging, KeySet::from_keys(&get_object_tagging_keys)); - map.insert(Action::DeleteObjectTagging, KeySet::from_keys(&get_object_tagging_keys)); - - map.insert(Action::PutObjectVersionTagging, KeySet::from_keys(&put_object_tagging_keys)); - map.insert(Action::GetObjectVersionTagging, KeySet::from_keys(&get_object_tagging_keys)); - map.insert(Action::GetObjectVersion, KeySet::from_keys(&get_object_tagging_keys)); - - let mut delete_object_version_keys = common_keys.clone(); - delete_object_version_keys.extend(vec![KeyName::S3VersionID.to_key()]); - - map.insert(Action::DeleteObjectVersion, KeySet::from_keys(&delete_object_version_keys)); - map.insert(Action::DeleteObjectVersionTagging, KeySet::from_keys(&get_object_tagging_keys)); - - map.insert(Action::GetReplicationConfiguration, KeySet::from_keys(&common_keys)); - map.insert(Action::PutReplicationConfiguration, KeySet::from_keys(&common_keys)); - - map.insert(Action::ReplicateObject, KeySet::from_keys(&get_object_tagging_keys)); - map.insert(Action::ReplicateDelete, KeySet::from_keys(&get_object_tagging_keys)); - map.insert(Action::ReplicateTags, KeySet::from_keys(&get_object_tagging_keys)); - map.insert(Action::GetObjectVersionForReplication, KeySet::from_keys(&get_object_tagging_keys)); - - map.insert(Action::RestoreObject, KeySet::from_keys(&common_keys)); - map.insert(Action::ResetBucketReplicationState, KeySet::from_keys(&common_keys)); - map.insert(Action::PutObjectFanOut, KeySet::from_keys(&common_keys)); - - ActionConditionKeyMap(map) -} diff --git a/ecstore/src/bucket/policy/bucket_policy.rs b/ecstore/src/bucket/policy/bucket_policy.rs deleted file mode 100644 index fd3488b0..00000000 --- a/ecstore/src/bucket/policy/bucket_policy.rs +++ /dev/null @@ -1,259 +0,0 @@ -use common::error::{Error, Result}; -// use rmp_serde::Serializer as rmpSerializer; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -use super::{ - action::{Action, ActionSet, IAMActionConditionKeyMap}, - condition::function::Functions, - effect::Effect, - principal::Principal, - resource::ResourceSet, -}; - -const DEFAULT_VERSION: &str = "2012-10-17"; - -#[derive(Debug, Deserialize, Serialize, Default, Clone)] -pub struct BucketPolicyArgs { - pub account_name: String, - pub groups: Vec, - pub action: Action, - pub bucket_name: String, - pub condition_values: HashMap>, - pub is_owner: bool, - pub object_name: String, -} - -#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] -#[serde(rename_all = "PascalCase", default)] -pub struct BPStatement { - #[serde(rename = "Sid")] - pub sid: String, - #[serde(rename = "Effect")] - pub effect: Effect, - #[serde(rename = "Principal")] - pub principal: Principal, - #[serde(rename = "Action")] - pub actions: ActionSet, - #[serde(rename = "NotAction", skip_serializing_if = "ActionSet::is_empty")] - pub not_actions: ActionSet, - #[serde(rename = "Resource", skip_serializing_if = "ResourceSet::is_empty")] - pub resources: ResourceSet, - #[serde(rename = "Condition", skip_serializing_if = "Functions::is_empty")] - pub conditions: Functions, -} - -impl BPStatement { - // pub fn equals(&self, other: &BPStatement) -> bool { - // if self.effect != other.effect { - // return false; - // } - - // if !self.principal.equals(other.principal) { - // return false; - // } - - // if !self.actions.equals(other.actions) { - // return false; - // } - // if !self.not_actions.equals(other.not_actions) { - // return false; - // } - // if !self.resources.equals(other.resources) { - // return false; - // } - // if !self.conditions.equals(other.conditions) { - // return false; - // } - - // true - // } - pub fn validate(&self, bucket: &str) -> Result<()> { - self.is_valid()?; - self.resources.validate_bucket(bucket) - } - pub fn is_valid(&self) -> Result<()> { - if !self.effect.is_valid() { - return Err(Error::msg(format!("invalid Effect {:?}", self.effect))); - } - - if !self.principal.is_valid() { - return Err(Error::msg(format!("invalid Principal {:?}", self.principal))); - } - - if self.actions.is_empty() && self.not_actions.is_empty() { - return Err(Error::msg("Action must not be empty")); - } - - if self.resources.as_ref().is_empty() { - return Err(Error::msg("Resource must not be empty")); - } - - for act in self.actions.as_ref() { - if act.is_object_action() { - if !self.resources.object_resource_exists() { - return Err(Error::msg(format!( - "unsupported object Resource found {:?} for action {:?}", - self.resources, act - ))); - } - } else if !self.resources.bucket_resource_exists() { - return Err(Error::msg(format!( - "unsupported bucket Resource found {:?} for action {:?}", - self.resources, act - ))); - } - - let key_diff = self.conditions.keys().difference(&IAMActionConditionKeyMap.lookup(act)); - if !key_diff.is_empty() { - return Err(Error::msg(format!( - "unsupported condition keys '{:?}' used for action '{:?}'", - key_diff, act - ))); - } - } - Ok(()) - } - fn is_allowed(&self, args: &BucketPolicyArgs) -> bool { - let check = || -> bool { - if !self.principal.is_match(&args.account_name) { - return false; - } - - if (!self.actions.is_match(&args.action) && !self.actions.is_empty()) || self.not_actions.is_match(&args.action) { - return false; - } - - let mut resource = args.bucket_name.clone(); - if !args.object_name.is_empty() { - if !args.object_name.starts_with('/') { - resource.push('/'); - } - - resource.push_str(&args.object_name); - } - - if !self.resources.is_match(&resource, &args.condition_values) { - return false; - } - - self.conditions.evaluate(&args.condition_values) - }; - - self.effect.is_allowed(check()) - } -} - -#[derive(Debug, Deserialize, Serialize, Default, Clone)] -// #[serde(rename_all = "PascalCase", default)] -pub struct BucketPolicy { - #[serde(rename = "ID", default)] - pub id: String, - #[serde(rename = "Version")] - pub version: String, - #[serde(rename = "Statement")] - pub statements: Vec, -} - -impl BucketPolicy { - pub fn is_allowed(&self, args: &BucketPolicyArgs) -> bool { - for statement in self.statements.iter() { - if statement.effect == Effect::Deny && !statement.is_allowed(args) { - return false; - } - } - - if args.is_owner { - return true; - } - - for statement in self.statements.iter() { - if statement.effect == Effect::Allow && statement.is_allowed(args) { - return true; - } - } - - false - } - - pub fn validate(&self, bucket: &str) -> Result<()> { - self.is_valid()?; - for statement in self.statements.iter() { - statement.validate(bucket)?; - } - Ok(()) - } - - pub fn is_valid(&self) -> Result<()> { - if self.version.as_str() != DEFAULT_VERSION && self.version.is_empty() { - return Err(Error::msg(format!("invalid version {}", self.version))); - } - - for statement in self.statements.iter() { - statement.is_valid()?; - } - Ok(()) - } - - pub fn is_empty(&self) -> bool { - self.statements.is_empty() - } - - pub fn marshal_msg(&self) -> Result { - let buf = serde_json::to_string(self)?; - - Ok(buf) - - // let mut buf = Vec::new(); - // self.serialize(&mut rmpSerializer::new(&mut buf).with_struct_map())?; - - // Ok(buf) - } - - pub fn unmarshal(buf: &[u8]) -> Result { - let mut p = serde_json::from_slice::(buf)?; - p.drop_duplicate_statements(); - Ok(p) - - // let t: BucketPolicy = rmp_serde::from_slice(buf)?; - // Ok(t) - } - - fn drop_duplicate_statements(&mut self) { - let mut dups = HashMap::new(); - - for v in self.statements.iter() { - if let Ok(data) = serde_json::to_string(self) { - dups.insert(data, v); - } - } - - let mut news = Vec::new(); - - for (_, v) in dups { - news.push(v.clone()); - } - - self.statements = news; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_bucket_policy() { - let json = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::dada\"],\"Sid\":\"\"},{\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::dada/*\"],\"Sid\":\"sdf\"}]}"; - - let a = BucketPolicy::unmarshal(json.to_string().as_bytes()).unwrap(); - - println!("{:?}", a); - - let j = a.marshal_msg(); - - println!("{:?}", j); - - println!("{:?}", json); - } -} diff --git a/ecstore/src/bucket/policy/condition/function.rs b/ecstore/src/bucket/policy/condition/function.rs deleted file mode 100644 index 929b2d4e..00000000 --- a/ecstore/src/bucket/policy/condition/function.rs +++ /dev/null @@ -1,304 +0,0 @@ -use super::{ - key::{Key, KeySet}, - keyname::KeyName, - name::Name, -}; -use serde::{ - de::{MapAccess, Visitor}, - ser::SerializeMap, - Deserialize, Serialize, -}; -use std::{ - collections::{HashMap, HashSet}, - fmt::{self, Debug, Display}, - marker::PhantomData, -}; - -// 定义ValueSet类型 -pub type ValueSet = HashSet; - -// 定义Function trait -pub trait FunctionApi: 'static + Send + Sync { - // evaluate方法 - fn evaluate(&self, values: &HashMap>) -> bool; - - // key方法 - fn key(&self) -> Key; - - // name方法 - fn name(&self) -> Name; - - // String方法 - fn to_string(&self) -> String; - - // to_map方法 - fn to_map(&self) -> HashMap; - - fn clone_box(&self) -> Box; -} - -// #[derive(Debug, Deserialize, Serialize, Clone)] -// pub enum Function { -// Test(TestFunction), -// } - -// impl FunctionApi for Function { -// // evaluate方法 -// fn evaluate(&self, values: &HashMap>) -> bool { -// match self { -// Function::Test(f) => f.evaluate(values), -// } -// } - -// // key方法 -// fn key(&self) -> Key { -// match self { -// Function::Test(f) => f.key(), -// } -// } - -// // name方法 -// fn name(&self) -> Name { -// match self { -// Function::Test(f) => f.name(), -// } -// } - -// // String方法 -// fn to_string(&self) -> String { -// match self { -// Function::Test(f) => f.to_string(), -// } -// } - -// // to_map方法 -// fn to_map(&self) -> HashMap { -// match self { -// Function::Test(f) => f.to_map(), -// } -// } - -// fn clone_box(&self) -> Box { -// match self { -// Function::Test(f) => f.clone_box(), -// } -// } -// } - -// 定义Functions类型 -#[derive(Default)] -pub struct Functions(Vec>); - -impl Functions { - pub fn evaluate(&self, values: &HashMap>) -> bool { - for f in self.0.iter() { - if f.evaluate(values) { - return true; - } - } - - false - } - pub fn keys(&self) -> KeySet { - let mut set = KeySet::new(); - for f in self.0.iter() { - set.add(f.key()) - } - set - } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl Debug for Functions { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let funs: Vec = self.0.iter().map(|v| v.to_string()).collect(); - f.debug_list().entries(funs.iter()).finish() - } -} - -impl Display for Functions { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let funs: Vec = self.0.iter().map(|v| v.to_string()).collect(); - write!(f, "{:?}", funs) - } -} - -impl Clone for Functions { - fn clone(&self) -> Self { - let mut list = Vec::new(); - for v in self.0.iter() { - list.push(v.clone_box()) - } - - Functions(list) - } -} - -impl PartialEq for Functions { - fn eq(&self, other: &Self) -> bool { - if self.0.len() != other.0.len() { - return false; - } - - for v in self.0.iter() { - let s = v.to_string(); - let mut found = false; - for o in other.0.iter() { - if s == o.to_string() { - found = true; - break; - } - } - - if !found { - return false; - } - } - - true - } -} - -impl Eq for Functions {} - -type FunctionsMap = HashMap>; - -impl Serialize for Functions { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut nm: FunctionsMap = HashMap::new(); - for f in self.0.iter() { - let fname = f.name().to_string(); - - if !nm.contains_key(&fname) { - nm.insert(fname.clone(), HashMap::new()); - } - - for (k, v) in f.to_map() { - if let Some(hm) = nm.get_mut(&fname) { - hm.insert(k.to_string(), v); - } - } - } - - let mut map = serializer.serialize_map(Some(nm.len()))?; - for (k, v) in nm.iter() { - map.serialize_entry(k, v)?; - } - - map.end() - } -} - -struct MyMapVisitor { - marker: PhantomData FunctionsMap>, -} - -impl MyMapVisitor { - fn new() -> Self { - MyMapVisitor { marker: PhantomData } - } -} - -// This is the trait that Deserializers are going to be driving. There -// is one method for each type of data that our type knows how to -// deserialize from. There are many other methods that are not -// implemented here, for example deserializing from integers or strings. -// By default those methods will return an error, which makes sense -// because we cannot deserialize a MyMap from an integer or string. -impl<'de> Visitor<'de> for MyMapVisitor { - // The type that our Visitor is going to produce. - type Value = FunctionsMap; - - // Format a message stating what data this Visitor expects to receive. - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a very special map") - } - - // Deserialize MyMap from an abstract "map" provided by the - // Deserializer. The MapAccess input is a callback provided by - // the Deserializer to let us see each entry in the map. - fn visit_map(self, mut access: M) -> Result - where - M: MapAccess<'de>, - { - let mut map = FunctionsMap::with_capacity(access.size_hint().unwrap_or(0)); - - // While there are entries remaining in the input, add them - // into our map. - while let Some((key, value)) = access.next_entry()? { - map.insert(key, value); - } - - Ok(map) - } -} - -// This is the trait that informs Serde how to deserialize MyMap. -impl<'de> Deserialize<'de> for Functions { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - // Instantiate our Visitor and ask the Deserializer to drive - // it over the input data, resulting in an instance of MyMap. - let map = deserializer.deserialize_map(MyMapVisitor::new())?; - - for (key, vals) in map.iter() { - println!("functions key {}, vals {:?}", key, vals); - } - // TODO: FIXME: create functions from name - - Ok(Functions(Vec::new())) - } -} - -// impl<'de> Deserialize<'de> for Functions { -// fn deserialize(deserializer: D) -> Result -// where -// D: serde::Deserializer<'de>, -// { -// todo!() -// } -// } - -#[derive(Debug, Deserialize, Serialize, Default, Clone)] -pub struct TestFunction {} - -impl FunctionApi for TestFunction { - // evaluate方法 - fn evaluate(&self, _values: &HashMap>) -> bool { - true - } - - // key方法 - fn key(&self) -> Key { - Key { - name: KeyName::JWTPrefUsername, - variable: "".to_string(), - } - } - - // name方法 - fn name(&self) -> Name { - Name::StringEquals - } - - // String方法 - fn to_string(&self) -> String { - Name::StringEquals.to_string() - } - - // to_map方法 - fn to_map(&self) -> HashMap { - HashMap::new() - } - - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} diff --git a/ecstore/src/bucket/policy/condition/key.rs b/ecstore/src/bucket/policy/condition/key.rs deleted file mode 100644 index faa51a18..00000000 --- a/ecstore/src/bucket/policy/condition/key.rs +++ /dev/null @@ -1,155 +0,0 @@ -use super::keyname::{KeyName, ALL_SUPPORT_KEYS}; -use common::error::Error; -use serde::{Deserialize, Serialize}; -use std::{collections::HashSet, fmt, str::FromStr}; - -// 定义Key结构体 -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Key { - pub name: KeyName, - pub variable: String, -} - -impl Key { - pub fn new(name: KeyName, variable: String) -> Self { - Key { name, variable } - } - // IsValid - checks if key is valid or not. - fn is_valid(&self) -> bool { - ALL_SUPPORT_KEYS.iter().any(|supported| self.name == *supported) - } - - // Is - checks if this key has the same key name or not. - pub fn is(&self, name: &KeyName) -> bool { - self.name == *name - } - - // VarName - returns variable key name, such as "${aws:username}" - pub fn var_name(&self) -> String { - self.name.var_name() - } - - // Name - returns key name which is stripped value of prefixes "aws:" and "s3:" - pub fn name(&self) -> String { - if !self.variable.is_empty() { - format!("{}{}", self.name.name(), self.variable) - } else { - self.name.name().to_string() - } - } -} - -impl FromStr for Key { - type Err = Error; - - fn from_str(s: &str) -> Result { - let (name, variable) = if let Some(pos) = s.find('/') { - (&s[..pos], &s[pos + 1..]) - } else { - (s, "") - }; - - let keyname = KeyName::from_str(name)?; - - let key = Key { - name: keyname, - variable: variable.to_string(), - }; - - if key.is_valid() { - Ok(key) - } else { - Err(Error::msg(format!("invalid condition key '{}'", s))) - } - } -} - -impl Serialize for Key { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.to_string().as_str()) - } -} - -impl<'de> Deserialize<'de> for Key { - fn deserialize(deserializer: D) -> Result - where - D: serde::de::Deserializer<'de>, - { - let s: String = Deserialize::deserialize(deserializer)?; - Key::from_str(s.as_str()).map_err(serde::de::Error::custom) - } -} - -impl fmt::Display for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if !self.variable.is_empty() { - write!(f, "{}/{}", self.name.as_str(), self.variable) - } else { - write!(f, "{}", self.name) - } - } -} - -#[derive(Debug, Default)] -pub struct KeySet(HashSet); - -impl KeySet { - pub fn new() -> Self { - KeySet(HashSet::new()) - } - // Add - add a key to key set - pub fn add(&mut self, key: Key) { - self.0.insert(key); - } - - // Merge merges two key sets, duplicates are overwritten - pub fn merge(&mut self, other: &KeySet) { - for key in &other.0 { - self.add(key.clone()); - } - } - - // Match matches the input key name with current keySet - pub fn match_key(&self, key: &Key) -> bool { - self.0.contains(key) - } - - // Difference - returns a key set contains difference of two keys - pub fn difference(&self, other: &KeySet) -> KeySet { - let mut result = KeySet::default(); - for key in &self.0 { - if !other.match_key(key) { - result.add(key.clone()); - } - } - result - } - - // IsEmpty - returns whether key set is empty or not - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - // ToSlice - returns slice of keys - fn to_slice(&self) -> Vec { - self.0.iter().cloned().collect() - } - - // NewKeySet - returns new KeySet contains given keys - pub fn from_keys(keys: &Vec) -> KeySet { - let mut set = KeySet::default(); - for key in keys { - set.add(key.clone()); - } - set - } -} - -impl fmt::Display for KeySet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.to_slice()) - } -} diff --git a/ecstore/src/bucket/policy/condition/keyname.rs b/ecstore/src/bucket/policy/condition/keyname.rs deleted file mode 100644 index b2fe2df9..00000000 --- a/ecstore/src/bucket/policy/condition/keyname.rs +++ /dev/null @@ -1,475 +0,0 @@ -use core::fmt; -use lazy_static::lazy_static; -use serde::{Deserialize, Serialize}; -use std::str::FromStr; - -use common::error::Error; - -use super::key::Key; - -// 定义KeyName枚举类型 -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum KeyName { - // S3XAmzCopySource - key representing x-amz-copy-source HTTP header applicable to PutObject API only. - S3XAmzCopySource, // KeyName = "s3:x-amz-copy-source" - - // S3XAmzServerSideEncryption - key representing x-amz-server-side-encryption HTTP header applicable - // to PutObject API only. - S3XAmzServerSideEncryption, // KeyName = "s3:x-amz-server-side-encryption" - - // S3XAmzServerSideEncryptionCustomerAlgorithm - key representing - // x-amz-server-side-encryption-customer-algorithm HTTP header applicable to PutObject API only. - S3XAmzServerSideEncryptionCustomerAlgorithm, // KeyName = "s3:x-amz-server-side-encryption-customer-algorithm" - - // S3XAmzMetadataDirective - key representing x-amz-metadata-directive HTTP header applicable to - // PutObject API only. - S3XAmzMetadataDirective, // KeyName = "s3:x-amz-metadata-directive" - - // S3XAmzContentSha256 - set a static content-sha256 for all calls for a given action. - S3XAmzContentSha256, // KeyName = "s3:x-amz-content-sha256" - - // S3XAmzStorageClass - key representing x-amz-storage-class HTTP header applicable to PutObject API - // only. - S3XAmzStorageClass, // KeyName = "s3:x-amz-storage-class" - - // S3XAmzServerSideEncryptionAwsKmsKeyID - key representing x-amz-server-side-encryption-aws-kms-key-id - // HTTP header for S3 API calls - S3XAmzServerSideEncryptionAwsKmsKeyID, // KeyName = "s3:x-amz-server-side-encryption-aws-kms-key-id" - - // S3LocationConstraint - key representing LocationConstraint XML tag of CreateBucket API only. - S3LocationConstraint, // KeyName = "s3:LocationConstraint" - - // S3Prefix - key representing prefix query parameter of ListBucket API only. - S3Prefix, // KeyName = "s3:prefix" - - // S3Delimiter - key representing delimiter query parameter of ListBucket API only. - S3Delimiter, // KeyName = "s3:delimiter" - - // S3VersionID - Enables you to limit the permission for the - // s3:PutObjectVersionTagging action to a specific object version. - S3VersionID, // KeyName = "s3:versionid" - - // S3MaxKeys - key representing max-keys query parameter of ListBucket API only. - S3MaxKeys, // KeyName = "s3:max-keys" - - // S3ObjectLockRemainingRetentionDays - key representing object-lock-remaining-retention-days - // Enables enforcement of an object relative to the remaining retention days, you can set - // minimum and maximum allowable retention periods for a bucket using a bucket policy. - // This key are specific for s3:PutObjectRetention API. - S3ObjectLockRemainingRetentionDays, // KeyName = "s3:object-lock-remaining-retention-days" - - // S3ObjectLockMode - key representing object-lock-mode - // Enables enforcement of the specified object retention mode - S3ObjectLockMode, // KeyName = "s3:object-lock-mode" - - // S3ObjectLockRetainUntilDate - key representing object-lock-retain-util-date - // Enables enforcement of a specific retain-until-date - S3ObjectLockRetainUntilDate, // KeyName = "s3:object-lock-retain-until-date" - - // S3ObjectLockLegalHold - key representing object-local-legal-hold - // Enables enforcement of the specified object legal hold status - S3ObjectLockLegalHold, // KeyName = "s3:object-lock-legal-hold" - - // AWSReferer - key representing Referer header of any API. - AWSReferer, // KeyName = "aws:Referer" - - // AWSSourceIP - key representing client's IP address (not intermittent proxies) of any API. - AWSSourceIP, // KeyName = "aws:SourceIp" - - // AWSUserAgent - key representing UserAgent header for any API. - AWSUserAgent, // KeyName = "aws:UserAgent" - - // AWSSecureTransport - key representing if the clients request is authenticated or not. - AWSSecureTransport, // KeyName = "aws:SecureTransport" - - // AWSCurrentTime - key representing the current time. - AWSCurrentTime, // KeyName = "aws:CurrentTime" - - // AWSEpochTime - key representing the current epoch time. - AWSEpochTime, // KeyName = "aws:EpochTime" - - // AWSPrincipalType - user principal type currently supported values are "User" and "Anonymous". - AWSPrincipalType, // KeyName = "aws:principaltype" - - // AWSUserID - user unique ID, in RustFS this value is same as your user Access Key. - AWSUserID, // KeyName = "aws:userid" - - // AWSUsername - user friendly name, in RustFS this value is same as your user Access Key. - AWSUsername, // KeyName = "aws:username" - - // AWSGroups - groups for any authenticating Access Key. - AWSGroups, // KeyName = "ss" - - // S3SignatureVersion - identifies the version of AWS Signature that you want to support for authenticated requests. - S3SignatureVersion, // KeyName = "s3:signatureversion" - - // S3SignatureAge - identifies the maximum age of presgiend URL allowed - S3SignatureAge, // KeyName = "s3:signatureAge" - - // S3AuthType - optionally use this condition key to restrict incoming requests to use a specific authentication method. - S3AuthType, // KeyName = "s3:authType" - - // Refer https://docs.aws.amazon.com/AmazonS3/latest/userguide/tagging-and-policies.html - ExistingObjectTag, // KeyName = "s3:ExistingObjectTag" - RequestObjectTagKeys, // KeyName = "s3:RequestObjectTagKeys" - RequestObjectTag, // KeyName = "s3:RequestObjectTag" - - // JWTSub - JWT subject claim substitution. - JWTSub, //KeyName = "jwt:sub" - - // JWTIss issuer claim substitution. - JWTIss, //KeyName = "jwt:iss" - - // JWTAud audience claim substitution. - JWTAud, //KeyName = "jwt:aud" - - // JWTJti JWT unique identifier claim substitution. - JWTJti, //KeyName = "jwt:jti" - - JWTUpn, //KeyName = "jwt:upn" - JWTName, //KeyName = "jwt:name" - JWTGroups, //KeyName = "jwt:groups" - JWTGivenName, //KeyName = "jwt:given_name" - JWTFamilyName, //KeyName = "jwt:family_name" - JWTMiddleName, //KeyName = "jwt:middle_name" - JWTNickName, //KeyName = "jwt:nickname" - JWTPrefUsername, //KeyName = "jwt:preferred_username" - JWTProfile, //KeyName = "jwt:profile" - JWTPicture, //KeyName = "jwt:picture" - JWTWebsite, //KeyName = "jwt:website" - JWTEmail, //KeyName = "jwt:email" - JWTGender, //KeyName = "jwt:gender" - JWTBirthdate, //KeyName = "jwt:birthdate" - JWTPhoneNumber, //KeyName = "jwt:phone_number" - JWTAddress, //KeyName = "jwt:address" - JWTScope, //KeyName = "jwt:scope" - JWTClientID, //KeyName = "jwt:client_id" - - // LDAPUser - LDAP username, this value is equal to your authenticating LDAP user DN. - LDAPUser, // KeyName = "ldap:user" - - // LDAPUsername - LDAP username, is the authenticated simple user. - LDAPUsername, // KeyName = "ldap:username" - - // LDAPGroups - LDAP groups, this value is equal LDAP Group DNs for the authenticating user. - LDAPGroups, // KeyName = "ldap:groups" - - // STSDurationSeconds - Duration seconds condition for STS policy - STSDurationSeconds, // KeyName = "sts:DurationSeconds" - // SVCDurationSeconds - Duration seconds condition for Admin policy - SVCDurationSeconds, // KeyName = "svc:DurationSeconds" - - Undefined, -} - -lazy_static! { - pub static ref JWTKEYS: Vec = { - vec![ - KeyName::JWTSub, - KeyName::JWTIss, - KeyName::JWTAud, - KeyName::JWTJti, - KeyName::JWTName, - KeyName::JWTUpn, - KeyName::JWTGroups, - KeyName::JWTGivenName, - KeyName::JWTFamilyName, - KeyName::JWTMiddleName, - KeyName::JWTNickName, - KeyName::JWTPrefUsername, - KeyName::JWTProfile, - KeyName::JWTPicture, - KeyName::JWTWebsite, - KeyName::JWTEmail, - KeyName::JWTGender, - KeyName::JWTBirthdate, - KeyName::JWTPhoneNumber, - KeyName::JWTAddress, - KeyName::JWTScope, - KeyName::JWTClientID, - ] - }; - pub static ref ALL_SUPPORT_KEYS: Vec = { - vec![ - KeyName::S3SignatureVersion, - KeyName::S3AuthType, - KeyName::S3SignatureAge, - KeyName::S3XAmzCopySource, - KeyName::S3XAmzServerSideEncryption, - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm, - KeyName::S3XAmzMetadataDirective, - KeyName::S3XAmzStorageClass, - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID, - KeyName::S3XAmzContentSha256, - KeyName::S3LocationConstraint, - KeyName::S3Prefix, - KeyName::S3Delimiter, - KeyName::S3MaxKeys, - KeyName::S3VersionID, - KeyName::S3ObjectLockRemainingRetentionDays, - KeyName::S3ObjectLockMode, - KeyName::S3ObjectLockLegalHold, - KeyName::S3ObjectLockRetainUntilDate, - KeyName::AWSReferer, - KeyName::AWSSourceIP, - KeyName::AWSUserAgent, - KeyName::AWSSecureTransport, - KeyName::AWSCurrentTime, - KeyName::AWSEpochTime, - KeyName::AWSPrincipalType, - KeyName::AWSUserID, - KeyName::AWSUsername, - KeyName::AWSGroups, - KeyName::LDAPUser, - KeyName::LDAPUsername, - KeyName::LDAPGroups, - KeyName::RequestObjectTag, - KeyName::ExistingObjectTag, - KeyName::RequestObjectTagKeys, - KeyName::JWTSub, - KeyName::JWTIss, - KeyName::JWTAud, - KeyName::JWTJti, - KeyName::JWTName, - KeyName::JWTUpn, - KeyName::JWTGroups, - KeyName::JWTGivenName, - KeyName::JWTFamilyName, - KeyName::JWTMiddleName, - KeyName::JWTNickName, - KeyName::JWTPrefUsername, - KeyName::JWTProfile, - KeyName::JWTPicture, - KeyName::JWTWebsite, - KeyName::JWTEmail, - KeyName::JWTGender, - KeyName::JWTBirthdate, - KeyName::JWTPhoneNumber, - KeyName::JWTAddress, - KeyName::JWTScope, - KeyName::JWTClientID, - KeyName::STSDurationSeconds, - KeyName::SVCDurationSeconds, - ] - }; - pub static ref COMMOM_KEYS: Vec = { - let mut keys = vec![ - KeyName::S3SignatureVersion, - KeyName::S3AuthType, - KeyName::S3SignatureAge, - KeyName::S3XAmzContentSha256, - KeyName::S3LocationConstraint, - KeyName::AWSReferer, - KeyName::AWSSourceIP, - KeyName::AWSUserAgent, - KeyName::AWSSecureTransport, - KeyName::AWSCurrentTime, - KeyName::AWSEpochTime, - KeyName::AWSPrincipalType, - KeyName::AWSUserID, - KeyName::AWSUsername, - KeyName::AWSGroups, - KeyName::LDAPUser, - KeyName::LDAPUsername, - KeyName::LDAPGroups, - ]; - - keys.extend(JWTKEYS.iter().cloned()); - - keys - }; - pub static ref ALL_SUPPORT_ADMIN_KEYS: Vec = { - let mut keys = vec![ - KeyName::AWSReferer, - KeyName::AWSSourceIP, - KeyName::AWSUserAgent, - KeyName::AWSSecureTransport, - KeyName::AWSCurrentTime, - KeyName::AWSEpochTime, - KeyName::AWSPrincipalType, - KeyName::AWSUserID, - KeyName::AWSUsername, - KeyName::AWSGroups, - KeyName::LDAPUser, - KeyName::LDAPUsername, - KeyName::LDAPGroups, - KeyName::SVCDurationSeconds, - ]; - - keys.extend(JWTKEYS.iter().cloned()); - - keys - }; - pub static ref ALL_SUPPORT_STS_KEYS: Vec = vec![KeyName::STSDurationSeconds]; -} - -// 实现KeyName枚举的方法 -impl KeyName { - pub fn name(&self) -> &str { - let name = self.as_str(); - if name.starts_with("aws:") { - name.trim_start_matches("aws:") - } else if name.starts_with("jwt:") { - name.trim_start_matches("jwt:") - } else if name.starts_with("ldap:") { - name.trim_start_matches("ldap:") - } else if name.starts_with("sts:") { - name.trim_start_matches("sts:") - } else if name.starts_with("svc:") { - name.trim_start_matches("svc:") - } else { - name.trim_start_matches("s3:") - } - } - - // Name方法,返回键名的名称 - pub fn as_str(&self) -> &str { - match self { - KeyName::S3XAmzCopySource => "s3:x-amz-copy-source", - KeyName::S3XAmzServerSideEncryption => "s3:x-amz-server-side-encryption", - KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm => "s3:x-amz-server-side-encryption-customer-algorithm", - KeyName::S3XAmzMetadataDirective => "s3:x-amz-metadata-directive", - KeyName::S3XAmzContentSha256 => "s3:x-amz-content-sha256", - KeyName::S3XAmzStorageClass => "s3:x-amz-storage-class", - KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID => "s3:x-amz-server-side-encryption-aws-kms-key-id", - KeyName::S3LocationConstraint => "s3:LocationConstraint", - KeyName::S3Prefix => "s3:prefix", - KeyName::S3Delimiter => "s3:delimiter", - KeyName::S3VersionID => "s3:versionid", - KeyName::S3MaxKeys => "s3:max-keys", - KeyName::S3ObjectLockRemainingRetentionDays => "s3:object-lock-remaining-retention-days", - KeyName::S3ObjectLockMode => "s3:object-lock-mode", - KeyName::S3ObjectLockRetainUntilDate => "s3:object-lock-retain-until-date", - KeyName::S3ObjectLockLegalHold => "s3:object-lock-legal-hold", - KeyName::AWSReferer => "aws:Referer", - KeyName::AWSSourceIP => "aws:SourceIp", - KeyName::AWSUserAgent => "aws:UserAgent", - KeyName::AWSSecureTransport => "aws:SecureTransport", - KeyName::AWSCurrentTime => "aws:CurrentTime", - KeyName::AWSEpochTime => "aws:EpochTime", - KeyName::AWSPrincipalType => "aws:principaltype", - KeyName::AWSUserID => "aws:userid", - KeyName::AWSUsername => "aws:username", - KeyName::AWSGroups => "ss", - KeyName::S3SignatureVersion => "s3:signatureversion", - KeyName::S3SignatureAge => "s3:signatureAge", - KeyName::S3AuthType => "s3:authType", - KeyName::ExistingObjectTag => "s3:ExistingObjectTag", - KeyName::RequestObjectTagKeys => "s3:RequestObjectTagKeys", - KeyName::RequestObjectTag => "s3:RequestObjectTag", - KeyName::JWTSub => "jwt:sub", - KeyName::JWTIss => "jwt:iss", - KeyName::JWTAud => "jwt:aud", - KeyName::JWTJti => "jwt:jti", - KeyName::JWTUpn => "jwt:upn", - KeyName::JWTName => "jwt:name", - KeyName::JWTGroups => "jwt:groups", - KeyName::JWTGivenName => "jwt:given_name", - KeyName::JWTFamilyName => "jwt:family_name", - KeyName::JWTMiddleName => "jwt:middle_name", - KeyName::JWTNickName => "jwt:nickname", - KeyName::JWTPrefUsername => "jwt:preferred_username", - KeyName::JWTProfile => "jwt:profile", - KeyName::JWTPicture => "jwt:picture", - KeyName::JWTWebsite => "jwt:website", - KeyName::JWTEmail => "jwt:email", - KeyName::JWTGender => "jwt:gender", - KeyName::JWTBirthdate => "jwt:birthdate", - KeyName::JWTPhoneNumber => "jwt:phone_number", - KeyName::JWTAddress => "jwt:address", - KeyName::JWTScope => "jwt:scope", - KeyName::JWTClientID => "jwt:client_id", - KeyName::LDAPUser => "ldap:user", - KeyName::LDAPUsername => "ldap:username", - KeyName::LDAPGroups => "ldap:groups", - KeyName::STSDurationSeconds => "sts:DurationSeconds", - KeyName::SVCDurationSeconds => "svc:DurationSeconds", - KeyName::Undefined => "", - } - } - - // VarName方法,返回变量键名,例如 "${aws:username}" - pub fn var_name(&self) -> String { - format!("${{{}}}", self.name()) - } - - // ToKey方法,从名称创建键 - pub fn to_key(&self) -> Key { - Key::new(self.clone(), "".to_string()) - } -} - -impl fmt::Display for KeyName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.as_str()) - } -} - -impl FromStr for KeyName { - type Err = Error; - - fn from_str(s: &str) -> Result { - match s { - "s3:x-amz-copy-source" => Ok(KeyName::S3XAmzCopySource), - "s3:x-amz-server-side-encryption" => Ok(KeyName::S3XAmzServerSideEncryption), - "s3:x-amz-server-side-encryption-customer-algorithm" => Ok(KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm), - "s3:x-amz-metadata-directive" => Ok(KeyName::S3XAmzMetadataDirective), - "s3:x-amz-content-sha256" => Ok(KeyName::S3XAmzContentSha256), - "s3:x-amz-storage-class" => Ok(KeyName::S3XAmzStorageClass), - "s3:x-amz-server-side-encryption-aws-kms-key-id" => Ok(KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID), - "s3:LocationConstraint" => Ok(KeyName::S3LocationConstraint), - "s3:prefix" => Ok(KeyName::S3Prefix), - "s3:delimiter" => Ok(KeyName::S3Delimiter), - "s3:versionid" => Ok(KeyName::S3VersionID), - "s3:max-keys" => Ok(KeyName::S3MaxKeys), - "s3:object-lock-remaining-retention-days" => Ok(KeyName::S3ObjectLockRemainingRetentionDays), - "s3:object-lock-mode" => Ok(KeyName::S3ObjectLockMode), - "s3:object-lock-retain-until-date" => Ok(KeyName::S3ObjectLockRetainUntilDate), - "s3:object-lock-legal-hold" => Ok(KeyName::S3ObjectLockLegalHold), - "aws:Referer" => Ok(KeyName::AWSReferer), - "aws:SourceIp" => Ok(KeyName::AWSSourceIP), - "aws:UserAgent" => Ok(KeyName::AWSUserAgent), - "aws:SecureTransport" => Ok(KeyName::AWSSecureTransport), - "aws:CurrentTime" => Ok(KeyName::AWSCurrentTime), - "aws:EpochTime" => Ok(KeyName::AWSEpochTime), - "aws:principaltype" => Ok(KeyName::AWSPrincipalType), - "aws:userid" => Ok(KeyName::AWSUserID), - "aws:username" => Ok(KeyName::AWSUsername), - "aws:groups" => Ok(KeyName::AWSGroups), - "s3:signatureversion" => Ok(KeyName::S3SignatureVersion), - "s3:signatureAge" => Ok(KeyName::S3SignatureAge), - "s3:authType" => Ok(KeyName::S3AuthType), - "s3:ExistingObjectTag" => Ok(KeyName::ExistingObjectTag), - "s3:RequestObjectTagKeys" => Ok(KeyName::RequestObjectTagKeys), - "s3:RequestObjectTag" => Ok(KeyName::RequestObjectTag), - "jwt:sub" => Ok(KeyName::JWTSub), - "jwt:iss" => Ok(KeyName::JWTIss), - "jwt:aud" => Ok(KeyName::JWTAud), - "jwt:jti" => Ok(KeyName::JWTJti), - "jwt:upn" => Ok(KeyName::JWTUpn), - "jwt:name" => Ok(KeyName::JWTName), - "jwt:groups" => Ok(KeyName::JWTGroups), - "jwt:given_name" => Ok(KeyName::JWTGivenName), - "jwt:family_name" => Ok(KeyName::JWTFamilyName), - "jwt:middle_name" => Ok(KeyName::JWTMiddleName), - "jwt:nickname" => Ok(KeyName::JWTNickName), - "jwt:preferred_username" => Ok(KeyName::JWTPrefUsername), - "jwt:profile" => Ok(KeyName::JWTProfile), - "jwt:picture" => Ok(KeyName::JWTPicture), - "jwt:website" => Ok(KeyName::JWTWebsite), - "jwt:email" => Ok(KeyName::JWTEmail), - "jwt:gender" => Ok(KeyName::JWTGender), - "jwt:birthdate" => Ok(KeyName::JWTBirthdate), - "jwt:phone_number" => Ok(KeyName::JWTPhoneNumber), - "jwt:address" => Ok(KeyName::JWTAddress), - "jwt:scope" => Ok(KeyName::JWTScope), - "jwt:client_id" => Ok(KeyName::JWTClientID), - "ldap:user" => Ok(KeyName::LDAPUser), - "ldap:username" => Ok(KeyName::LDAPUsername), - "ldap:groups" => Ok(KeyName::LDAPGroups), - "sts:DurationSeconds" => Ok(KeyName::STSDurationSeconds), - "svc:DurationSeconds" => Ok(KeyName::SVCDurationSeconds), - _ => Err(Error::msg(format!("keyname not found: {}", s))), - } - } -} diff --git a/ecstore/src/bucket/policy/condition/mod.rs b/ecstore/src/bucket/policy/condition/mod.rs deleted file mode 100644 index 46e6fa03..00000000 --- a/ecstore/src/bucket/policy/condition/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod function; -pub mod key; -pub mod keyname; -pub mod name; diff --git a/ecstore/src/bucket/policy/condition/name.rs b/ecstore/src/bucket/policy/condition/name.rs deleted file mode 100644 index be8541db..00000000 --- a/ecstore/src/bucket/policy/condition/name.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 定义Name枚举类型 -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Name { - StringEquals, - StringNotEquals, - StringEqualsIgnoreCase, - StringNotEqualsIgnoreCase, - StringLike, - StringNotLike, - BinaryEquals, - IpAddress, - NotIpAddress, - Null, - Bool, - NumericEquals, - NumericNotEquals, - NumericLessThan, - NumericLessThanEquals, - NumericGreaterThan, - NumericGreaterThanIfExists, - NumericGreaterThanEquals, - DateEquals, - DateNotEquals, - DateLessThan, - DateLessThanEquals, - DateGreaterThan, - DateGreaterThanEquals, - ForAllValues, - ForAnyValue, -} - -impl Name { - pub fn as_str(&self) -> &'static str { - match self { - Name::StringEquals => "StringEquals", - Name::StringNotEquals => "StringNotEquals", - Name::StringEqualsIgnoreCase => "StringEqualsIgnoreCase", - Name::StringNotEqualsIgnoreCase => "StringNotEqualsIgnoreCase", - Name::StringLike => "StringLike", - Name::StringNotLike => "StringNotLike", - Name::BinaryEquals => "BinaryEquals", - Name::IpAddress => "IpAddress", - Name::NotIpAddress => "NotIpAddress", - Name::Null => "Null", - Name::Bool => "Bool", - Name::NumericEquals => "NumericEquals", - Name::NumericNotEquals => "NumericNotEquals", - Name::NumericLessThan => "NumericLessThan", - Name::NumericLessThanEquals => "NumericLessThanEquals", - Name::NumericGreaterThan => "NumericGreaterThan", - Name::NumericGreaterThanIfExists => "NumericGreaterThanIfExists", - Name::NumericGreaterThanEquals => "NumericGreaterThanEquals", - Name::DateEquals => "DateEquals", - Name::DateNotEquals => "DateNotEquals", - Name::DateLessThan => "DateLessThan", - Name::DateLessThanEquals => "DateLessThanEquals", - Name::DateGreaterThan => "DateGreaterThan", - Name::DateGreaterThanEquals => "DateGreaterThanEquals", - Name::ForAllValues => "ForAllValues", - Name::ForAnyValue => "ForAnyValue", - } - } -} - -// impl ToString for Name { -// fn to_string(&self) -> String { -// self.as_str().to_string() -// } -// } - -impl std::fmt::Display for Name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.as_str()) - } -} diff --git a/ecstore/src/bucket/policy/effect.rs b/ecstore/src/bucket/policy/effect.rs deleted file mode 100644 index 6ec86ef6..00000000 --- a/ecstore/src/bucket/policy/effect.rs +++ /dev/null @@ -1,40 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::str::FromStr; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)] -#[serde(rename_all = "PascalCase")] -pub enum Effect { - #[default] - Allow, - Deny, -} - -impl Effect { - pub fn is_allowed(self, b: bool) -> bool { - if self == Effect::Allow { - b - } else { - !b - } - } - - pub fn is_valid(self) -> bool { - match self { - Effect::Allow => true, - Effect::Deny => true, - } - } -} - -// 实现从字符串解析Effect的功能 -impl FromStr for Effect { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "Allow" => Ok(Effect::Allow), - "Deny" => Ok(Effect::Deny), - _ => Err(()), - } - } -} diff --git a/ecstore/src/bucket/policy/mod.rs b/ecstore/src/bucket/policy/mod.rs deleted file mode 100644 index a0d54685..00000000 --- a/ecstore/src/bucket/policy/mod.rs +++ /dev/null @@ -1,103 +0,0 @@ -// use std::collections::HashMap; - -// use action::Action; -// use s3s_policy::model::{Effect, Policy, Principal, PrincipalRule, Statement}; -// use serde::{Deserialize, Serialize}; -// use tower::ready_cache::cache::Equivalent; - -// use crate::utils::wildcard; - -pub mod action; -pub mod bucket_policy; -pub mod condition; -pub mod effect; -pub mod principal; -pub mod resource; - -// #[derive(Debug, Deserialize, Serialize, Default, Clone)] -// pub struct BucketPolicyArgs { -// pub account_name: String, -// pub groups: Vec, -// pub action: Action, -// pub bucket_name: String, -// pub condition_values: HashMap>, -// pub is_owner: bool, -// pub object_name: String, -// } - -// pub trait AllowApi { -// fn is_allowed(&self, args: &BucketPolicyArgs) -> bool; -// } - -// pub trait MatchApi { -// fn is_match(&self, found: &str) -> bool; -// } - -// impl AllowApi for Policy { -// fn is_allowed(&self, args: &BucketPolicyArgs) -> bool { -// for statement in self.statement.as_slice().iter() { -// if statement.effect == Effect::Deny { -// if !statement.is_allowed(args) { -// return false; -// } -// } -// } -// false -// } -// } - -// impl AllowApi for Statement { -// fn is_allowed(&self, args: &BucketPolicyArgs) -> bool { -// let check = || -> bool { -// if let Some(principal) = &self.principal { -// if !principal.is_match(&args.account_name) { -// return false; -// } -// } - -// false -// }; - -// self.effect.is_allowed(check()) -// } -// } - -// impl MatchApi for PrincipalRule { -// fn is_match(&self, found: &str) -> bool { -// match self { -// PrincipalRule::Principal(principal) => match principal { -// Principal::Wildcard => return true, -// Principal::Map(index_map) => { -// if let Some(keys) = index_map.get("AWS") { -// for key in keys.as_slice() { -// if wildcard::match_simple(key, found) { -// return true; -// } -// } -// } -// return false; -// } -// }, -// PrincipalRule::NotPrincipal(principal) => match principal { -// Principal::Wildcard => return true, -// Principal::Map(index_map) => todo!(), -// }, -// } - -// false -// } -// } - -// trait EffectApi { -// fn is_allowed(&self, b: bool) -> bool; -// } - -// impl EffectApi for Effect { -// fn is_allowed(&self, b: bool) -> bool { -// if self == &Effect::Allow { -// b -// } else { -// !b -// } -// } -// } diff --git a/ecstore/src/bucket/policy/principal.rs b/ecstore/src/bucket/policy/principal.rs deleted file mode 100644 index cff14c7b..00000000 --- a/ecstore/src/bucket/policy/principal.rs +++ /dev/null @@ -1,25 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::collections::HashSet; - -use crate::utils; - -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)] -#[serde(rename_all = "PascalCase", default)] -pub struct Principal { - #[serde(rename = "AWS")] - aws: HashSet, -} - -impl Principal { - pub fn is_valid(&self) -> bool { - !self.aws.is_empty() - } - pub fn is_match(&self, parincipal: &str) -> bool { - for pattern in self.aws.iter() { - if utils::wildcard::match_simple(pattern, parincipal) { - return true; - } - } - false - } -} diff --git a/ecstore/src/bucket/policy/resource.rs b/ecstore/src/bucket/policy/resource.rs deleted file mode 100644 index 03e15a49..00000000 --- a/ecstore/src/bucket/policy/resource.rs +++ /dev/null @@ -1,263 +0,0 @@ -use crate::{ - bucket::policy::condition::keyname::COMMOM_KEYS, - utils::{self, wildcard}, -}; -use common::error::{Error, Result}; -use core::fmt; -use serde::{Deserialize, Serialize}; -use std::{ - collections::{HashMap, HashSet}, - str::FromStr, -}; - -// 定义ResourceARNType枚举类型 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, Default)] -pub enum ResourceARNType { - #[default] - UnknownARN, - ResourceARNS3, - ResourceARNKMS, -} - -impl fmt::Display for ResourceARNType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ResourceARNType::UnknownARN => write!(f, ""), - ResourceARNType::ResourceARNS3 => write!(f, "{}", RESOURCE_ARN_PREFIX), - ResourceARNType::ResourceARNKMS => write!(f, "{}", RESOURCE_ARN_KMS_PREFIX), - } - } -} - -// 定义资源ARN前缀 -const RESOURCE_ARN_PREFIX: &str = "arn:aws:s3:::"; -const RESOURCE_ARN_KMS_PREFIX: &str = "arn:rustfs:kms::::"; - -// 定义Resource结构体 -#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)] -pub struct Resource { - pattern: String, - rtype: ResourceARNType, -} - -impl Resource { - pub fn new(pattern: &str) -> Self { - Self { - pattern: pattern.to_owned(), - rtype: ResourceARNType::ResourceARNS3, - } - } - pub fn validate_bucket(&self, bucket: &str) -> Result<()> { - self.validate()?; - if !wildcard::match_pattern(&self.pattern, bucket) - && !wildcard::match_as_pattern_prefix(&self.pattern, format!("{}/", bucket).as_str()) - { - return Err(Error::msg("bucket name does not match")); - } - Ok(()) - } - pub fn validate(&self) -> Result<()> { - if !self.is_valid() { - Err(Error::msg("invalid resource")) - } else { - Ok(()) - } - } - pub fn is_valid(&self) -> bool { - if self.rtype == ResourceARNType::UnknownARN { - return false; - } - if self.is_s3() && self.pattern.starts_with('/') { - return false; - } - if self.is_kms() && self.pattern.as_bytes().iter().any(|&v| v == b'/' || v == b'\\' || v == b'.') { - return false; - } - - !self.pattern.is_empty() - } - pub fn is_s3(&self) -> bool { - self.rtype == ResourceARNType::ResourceARNS3 - } - pub fn is_kms(&self) -> bool { - self.rtype == ResourceARNType::ResourceARNKMS - } - pub fn is_bucket_pattern(&self) -> bool { - !self.pattern.contains('/') || self.pattern.eq("*") - } - pub fn is_object_pattern(&self) -> bool { - self.pattern.contains('/') || self.pattern.contains('*') - } - pub fn is_match(&self, res: &str, condition_values: &HashMap>) -> bool { - let mut pattern = res.to_string(); - if !condition_values.is_empty() { - for key in COMMOM_KEYS.iter() { - if let Some(vals) = condition_values.get(key.name()) { - if let Some(v0) = vals.first() { - pattern = pattern.replace(key.name(), v0); - } - } - } - } - - let cp = utils::path::clean(res); - - if cp != "." && cp == pattern { - return true; - } - - wildcard::match_pattern(&pattern, res) - } -} - -impl fmt::Display for Resource { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}{}", self.rtype, self.pattern) - } -} - -impl FromStr for Resource { - type Err = serde_json::Error; - - fn from_str(s: &str) -> Result { - if s.starts_with(RESOURCE_ARN_PREFIX) { - let pattern = { - if let Some(val) = s.strip_prefix(RESOURCE_ARN_PREFIX) { - val.to_string() - } else { - s.to_string() - } - }; - Ok(Self { - rtype: ResourceARNType::ResourceARNS3, - pattern, - }) - } else if s.starts_with(RESOURCE_ARN_KMS_PREFIX) { - let pattern = { - if let Some(val) = s.strip_prefix(RESOURCE_ARN_KMS_PREFIX) { - val.to_string() - } else { - s.to_string() - } - }; - Ok(Self { - rtype: ResourceARNType::ResourceARNS3, - pattern, - }) - } else { - Ok(Self { - rtype: ResourceARNType::UnknownARN, - pattern: "".to_string(), - }) - } - } -} - -impl Serialize for Resource { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.to_string().as_str()) - } -} - -impl<'de> Deserialize<'de> for Resource { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct Visitor; - - #[allow(clippy::needless_lifetimes)] - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = Resource; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("string resource") - } - - fn visit_str(self, value: &str) -> Result - where - E: serde::de::Error, - { - match Resource::from_str(value) { - Ok(res) => Ok(res), - Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self)), - } - } - } - - deserializer.deserialize_any(Visitor) - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq)] -#[serde(transparent)] -pub struct ResourceSet(pub HashSet); - -impl ResourceSet { - pub fn validate_bucket(&self, bucket: &str) -> Result<()> { - for res in self.0.iter() { - res.validate_bucket(bucket)?; - } - Ok(()) - } - - pub fn is_match(&self, res: &str, condition_values: &HashMap>) -> bool { - for item in self.0.iter() { - if item.is_match(res, condition_values) { - return true; - } - } - - false - } - pub fn object_resource_exists(&self) -> bool { - for res in self.0.iter() { - if res.is_object_pattern() { - return true; - } - } - false - } - pub fn bucket_resource_exists(&self) -> bool { - for res in self.0.iter() { - if res.is_bucket_pattern() { - return true; - } - } - false - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl AsRef> for ResourceSet { - fn as_ref(&self) -> &HashSet { - &self.0 - } -} - -// impl Serialize for ResourceSet { -// fn serialize(&self, serializer: S) -> Result -// where -// S: serde::Serializer, -// { -// let ress: Vec = self.0.iter().cloned().collect(); -// serializer.collect_seq(ress) -// } -// } - -// impl<'de> Deserialize<'de> for ResourceSet { -// fn deserialize(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// let vec: Vec = Deserialize::deserialize(deserializer)?; -// let ha: HashSet = vec.into_iter().collect(); -// Ok(ResourceSet(ha)) -// } -// } diff --git a/ecstore/src/bucket/policy_sys.rs b/ecstore/src/bucket/policy_sys.rs index d14ebd30..e5682c18 100644 --- a/ecstore/src/bucket/policy_sys.rs +++ b/ecstore/src/bucket/policy_sys.rs @@ -1,16 +1,13 @@ -use super::{ - error::BucketMetadataError, - metadata_sys::get_bucket_metadata_sys, - policy::bucket_policy::{BucketPolicy, BucketPolicyArgs}, -}; +use super::{error::BucketMetadataError, metadata_sys::get_bucket_metadata_sys}; use common::error::Result; +use policy::policy::{BucketPolicy, BucketPolicyArgs}; use tracing::warn; pub struct PolicySys {} impl PolicySys { - pub async fn is_allowed(args: &BucketPolicyArgs) -> bool { - match Self::get(&args.bucket_name).await { + pub async fn is_allowed(args: &BucketPolicyArgs<'_>) -> bool { + match Self::get(args.bucket).await { Ok(cfg) => return cfg.is_allowed(args), Err(err) => { if !BucketMetadataError::BucketPolicyNotFound.is(&err) {