fix policy parse

This commit is contained in:
weisd
2025-02-12 17:29:55 +08:00
parent 4a60b31ae3
commit d00bfd6243
7 changed files with 292 additions and 5 deletions

View File

@@ -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)]

View File

@@ -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)
}

View File

@@ -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)]

View File

@@ -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(())
}
}

View File

@@ -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;

View File

@@ -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
View 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"
]
}
}
}
]
}