mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 01:30:33 +00:00
@@ -114,14 +114,124 @@ pub enum S3Action {
|
||||
#[cfg_attr(test, default)]
|
||||
#[strum(serialize = "s3:*")]
|
||||
AllActions,
|
||||
#[strum(serialize = "s3:AbortMultipartUpload")]
|
||||
AbortMultipartUploadAction,
|
||||
#[strum(serialize = "s3:CreateBucket")]
|
||||
CreateBucketAction,
|
||||
#[strum(serialize = "s3:DeleteBucket")]
|
||||
DeleteBucketAction,
|
||||
#[strum(serialize = "s3:ForceDeleteBucket")]
|
||||
ForceDeleteBucketAction,
|
||||
#[strum(serialize = "s3:DeleteBucketPolicy")]
|
||||
DeleteBucketPolicyAction,
|
||||
#[strum(serialize = "s3:DeleteBucketCors")]
|
||||
DeleteBucketCorsAction,
|
||||
#[strum(serialize = "s3:DeleteObject")]
|
||||
DeleteObjectAction,
|
||||
#[strum(serialize = "s3:GetBucketLocation")]
|
||||
GetBucketLocationAction,
|
||||
#[strum(serialize = "s3:GetBucketNotification")]
|
||||
GetBucketNotificationAction,
|
||||
#[strum(serialize = "s3:GetBucketPolicy")]
|
||||
GetBucketPolicyAction,
|
||||
#[strum(serialize = "s3:GetBucketCors")]
|
||||
GetBucketCorsAction,
|
||||
#[strum(serialize = "s3:GetObject")]
|
||||
GetObjectAction,
|
||||
#[strum(serialize = "s3:GetObjectAttributes")]
|
||||
GetObjectAttributesAction,
|
||||
#[strum(serialize = "s3:HeadBucket")]
|
||||
HeadBucketAction,
|
||||
#[strum(serialize = "s3:ListAllMyBuckets")]
|
||||
ListAllMyBucketsAction,
|
||||
#[strum(serialize = "s3:ListBucket")]
|
||||
ListBucketAction,
|
||||
#[strum(serialize = "s3:GetBucketPolicyStatus")]
|
||||
GetBucketPolicyStatusAction,
|
||||
#[strum(serialize = "s3:ListBucketVersions")]
|
||||
ListBucketVersionsAction,
|
||||
#[strum(serialize = "s3:ListBucketMultipartUploads")]
|
||||
ListBucketMultipartUploadsAction,
|
||||
#[strum(serialize = "s3:ListenNotification")]
|
||||
ListenNotificationAction,
|
||||
#[strum(serialize = "s3:ListenBucketNotification")]
|
||||
ListenBucketNotificationAction,
|
||||
#[strum(serialize = "s3:ListMultipartUploadParts")]
|
||||
ListMultipartUploadPartsAction,
|
||||
#[strum(serialize = "s3:PutBucketLifecycle")]
|
||||
PutBucketLifecycleAction,
|
||||
#[strum(serialize = "s3:GetBucketLifecycle")]
|
||||
GetBucketLifecycleAction,
|
||||
#[strum(serialize = "s3:PutBucketNotification")]
|
||||
PutBucketNotificationAction,
|
||||
#[strum(serialize = "s3:PutBucketPolicy")]
|
||||
PutBucketPolicyAction,
|
||||
#[strum(serialize = "s3:PutBucketCors")]
|
||||
PutBucketCorsAction,
|
||||
#[strum(serialize = "s3:PutObject")]
|
||||
PutObjectAction,
|
||||
#[strum(serialize = "s3:DeleteObjectVersion")]
|
||||
DeleteObjectVersionAction,
|
||||
#[strum(serialize = "s3:DeleteObjectVersionTagging")]
|
||||
DeleteObjectVersionTaggingAction,
|
||||
#[strum(serialize = "s3:GetObjectVersion")]
|
||||
GetObjectVersionAction,
|
||||
#[strum(serialize = "s3:GetObjectVersionAttributes")]
|
||||
GetObjectVersionAttributesAction,
|
||||
#[strum(serialize = "s3:GetObjectVersionTagging")]
|
||||
GetObjectVersionTaggingAction,
|
||||
#[strum(serialize = "s3:PutObjectVersionTagging")]
|
||||
PutObjectVersionTaggingAction,
|
||||
#[strum(serialize = "s3:BypassGovernanceRetention")]
|
||||
BypassGovernanceRetentionAction,
|
||||
#[strum(serialize = "s3:PutObjectRetention")]
|
||||
PutObjectRetentionAction,
|
||||
#[strum(serialize = "s3:GetObjectRetention")]
|
||||
GetObjectRetentionAction,
|
||||
#[strum(serialize = "s3:GetObjectLegalHold")]
|
||||
GetObjectLegalHoldAction,
|
||||
#[strum(serialize = "s3:PutObjectLegalHold")]
|
||||
PutObjectLegalHoldAction,
|
||||
#[strum(serialize = "s3:GetBucketObjectLockConfiguration")]
|
||||
GetBucketObjectLockConfigurationAction,
|
||||
#[strum(serialize = "s3:PutBucketObjectLockConfiguration")]
|
||||
PutBucketObjectLockConfigurationAction,
|
||||
#[strum(serialize = "s3:GetBucketTagging")]
|
||||
GetBucketTaggingAction,
|
||||
#[strum(serialize = "s3:PutBucketTagging")]
|
||||
PutBucketTaggingAction,
|
||||
#[strum(serialize = "s3:GetObjectTagging")]
|
||||
GetObjectTaggingAction,
|
||||
#[strum(serialize = "s3:PutObjectTagging")]
|
||||
PutObjectTaggingAction,
|
||||
#[strum(serialize = "s3:DeleteObjectTagging")]
|
||||
DeleteObjectTaggingAction,
|
||||
#[strum(serialize = "s3:PutBucketEncryption")]
|
||||
PutBucketEncryptionAction,
|
||||
#[strum(serialize = "s3:GetBucketEncryption")]
|
||||
GetBucketEncryptionAction,
|
||||
#[strum(serialize = "s3:PutBucketVersioning")]
|
||||
PutBucketVersioningAction,
|
||||
#[strum(serialize = "s3:GetBucketVersioning")]
|
||||
GetBucketVersioningAction,
|
||||
#[strum(serialize = "s3:GetReplicationConfiguration")]
|
||||
GetReplicationConfigurationAction,
|
||||
#[strum(serialize = "s3:PutReplicationConfiguration")]
|
||||
PutReplicationConfigurationAction,
|
||||
#[strum(serialize = "s3:ReplicateObject")]
|
||||
ReplicateObjectAction,
|
||||
#[strum(serialize = "s3:ReplicateDelete")]
|
||||
ReplicateDeleteAction,
|
||||
#[strum(serialize = "s3:ReplicateTags")]
|
||||
ReplicateTagsAction,
|
||||
#[strum(serialize = "s3:GetObjectVersionForReplication")]
|
||||
GetObjectVersionForReplicationAction,
|
||||
#[strum(serialize = "s3:RestoreObject")]
|
||||
RestoreObjectAction,
|
||||
#[strum(serialize = "s3:ResetBucketReplicationState")]
|
||||
ResetBucketReplicationStateAction,
|
||||
#[strum(serialize = "s3:PutObjectFanOut")]
|
||||
PutObjectFanOutAction,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Hash, PartialEq, Eq, Clone, EnumString, IntoStaticStr, Debug)]
|
||||
|
||||
@@ -131,9 +131,9 @@ impl<'de> Deserialize<'de> for Functions {
|
||||
}
|
||||
}
|
||||
|
||||
if inner_data.is_empty() {
|
||||
return Err(Error::custom("has no condition element"));
|
||||
}
|
||||
// if inner_data.is_empty() {
|
||||
// return Err(Error::custom("has no condition element"));
|
||||
// }
|
||||
|
||||
Ok(inner_data)
|
||||
}
|
||||
|
||||
@@ -169,6 +169,10 @@ pub enum S3KeyName {
|
||||
|
||||
#[strum(serialize = "s3:ExistingObjectTag")]
|
||||
S3ExistingObjectTag,
|
||||
#[strum(serialize = "s3:RequestObjectTagKeys")]
|
||||
S3RequestObjectTagKeys,
|
||||
#[strum(serialize = "s3:RequestObjectTag")]
|
||||
S3RequestObjectTag,
|
||||
}
|
||||
|
||||
#[derive(Clone, EnumString, Debug, IntoStaticStr, Eq, PartialEq, Serialize, Deserialize)]
|
||||
|
||||
@@ -6,8 +6,11 @@ use std::collections::HashSet;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
pub struct Policy {
|
||||
#[serde(default, rename = "ID")]
|
||||
pub id: ID,
|
||||
#[serde(rename = "Version")]
|
||||
pub version: String,
|
||||
#[serde(rename = "Statement")]
|
||||
pub statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
@@ -153,6 +156,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
),
|
||||
@@ -177,6 +181,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
),
|
||||
@@ -200,6 +205,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
),
|
||||
@@ -223,6 +229,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
),
|
||||
@@ -253,6 +260,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
),
|
||||
@@ -273,6 +281,7 @@ pub mod default {
|
||||
not_actions: ActionSet(Default::default()),
|
||||
resources: ResourceSet(HashSet::new()),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
},
|
||||
Statement {
|
||||
sid: "".into(),
|
||||
@@ -285,6 +294,7 @@ pub mod default {
|
||||
not_actions: ActionSet(Default::default()),
|
||||
resources: ResourceSet(HashSet::new()),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
},
|
||||
Statement {
|
||||
sid: "".into(),
|
||||
@@ -301,6 +311,7 @@ pub mod default {
|
||||
hash_set
|
||||
}),
|
||||
conditions: Functions::default(),
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -308,3 +319,76 @@ pub mod default {
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use ecstore::error::Result;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_policy() -> Result<()> {
|
||||
let data = r#"
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:GetObject"],
|
||||
"Resource": ["arn:aws:s3:::dada/*"],
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"s3:ExistingObjectTag/security": "public"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:DeleteObjectTagging"],
|
||||
"Resource": ["arn:aws:s3:::dada/*"],
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"s3:ExistingObjectTag/security": "public"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:DeleteObject"],
|
||||
"Resource": ["arn:aws:s3:::dada/*"]
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:PutObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::dada/*"
|
||||
],
|
||||
"Condition": {
|
||||
"ForAllValues:StringLike": {
|
||||
"s3:RequestObjectTagKeys": [
|
||||
"security",
|
||||
"virus"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
|
||||
let p = Policy::parse_config(data.as_bytes())?;
|
||||
|
||||
// println!("{:?}", p);
|
||||
|
||||
let str = serde_json::to_string(&p)?;
|
||||
|
||||
// println!("----- {}", str);
|
||||
|
||||
let _p2 = Policy::parse_config(str.as_bytes())?;
|
||||
// println!("33{:?}", p2);
|
||||
|
||||
// assert_eq!(p, p2);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ impl PartialEq for ResourceSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Serialize, Deserialize, Clone, Debug)]
|
||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||
pub enum Resource {
|
||||
S3(String),
|
||||
Kms(String),
|
||||
@@ -140,6 +140,28 @@ impl Validator for Resource {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Resource {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
Resource::S3(s) => serializer.serialize_str(&format!("{}{}", Self::S3_PREFIX, s)),
|
||||
Resource::Kms(s) => serializer.serialize_str(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Resource {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let value = String::deserialize(deserializer)?;
|
||||
Resource::try_from(value.as_str()).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::policy::resource::Resource;
|
||||
|
||||
@@ -6,11 +6,19 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
pub struct Statement {
|
||||
#[serde(rename = "Sid", default)]
|
||||
pub sid: ID,
|
||||
#[serde(rename = "Effect")]
|
||||
pub effect: Effect,
|
||||
#[serde(rename = "Action")]
|
||||
pub actions: ActionSet,
|
||||
#[serde(rename = "NotAction", default)]
|
||||
pub not_actions: ActionSet,
|
||||
#[serde(rename = "Resource", default)]
|
||||
pub resources: ResourceSet,
|
||||
#[serde(rename = "NotResource", default)]
|
||||
pub not_resources: ResourceSet,
|
||||
#[serde(rename = "Condition", default)]
|
||||
pub conditions: Functions,
|
||||
}
|
||||
|
||||
@@ -84,7 +92,7 @@ impl Validator for Statement {
|
||||
// check sid
|
||||
self.sid.is_valid()?;
|
||||
|
||||
if self.actions.is_empty() || self.not_actions.is_empty() {
|
||||
if self.actions.is_empty() && self.not_actions.is_empty() {
|
||||
return Err(IamError::NonAction.into());
|
||||
}
|
||||
|
||||
|
||||
59
scripts/test_policy.json
Normal file
59
scripts/test_policy.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:GetObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::dada/*"
|
||||
],
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"s3:ExistingObjectTag/security": "public"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:DeleteObjectTagging"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::dada/*"
|
||||
],
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"s3:ExistingObjectTag/security": "public"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:DeleteObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::dada/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:PutObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::dada/*"
|
||||
],
|
||||
"Condition": {
|
||||
"ForAllValues:StringLike": {
|
||||
"s3:RequestObjectTagKeys": [
|
||||
"security",
|
||||
"virus"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user