mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-23 04:39:04 +00:00
fix(policy): accept legacy bucket policy ID field (#6362)
This commit is contained in:
@@ -195,7 +195,8 @@ pub struct BucketPolicyArgs<'a> {
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct BucketPolicy {
|
||||
#[serde(default, rename = "Id", skip_serializing_if = "ID::is_empty")]
|
||||
// RUSTFS_COMPAT_TODO(rustfs-6339): accept bucket policies persisted with the legacy "ID" key. Remove after migration tooling rewrites every retained legacy bucket policy.
|
||||
#[serde(default, rename = "Id", alias = "ID", skip_serializing_if = "ID::is_empty")]
|
||||
pub id: ID,
|
||||
#[serde(rename = "Version")]
|
||||
pub version: String,
|
||||
@@ -2786,7 +2787,7 @@ mod test {
|
||||
let parsed: serde_json::Value = serde_json::from_str(&json).expect("Should parse");
|
||||
|
||||
// Verify empty fields are omitted
|
||||
assert!(!parsed.as_object().unwrap().contains_key("ID"), "Empty ID should be omitted");
|
||||
assert!(parsed.get("Id").is_none(), "Empty ID should be omitted");
|
||||
|
||||
let statement = &parsed["Statement"][0];
|
||||
assert!(!statement.as_object().unwrap().contains_key("Sid"), "Empty Sid should be omitted");
|
||||
@@ -2809,6 +2810,43 @@ mod test {
|
||||
assert_eq!(statement["Principal"]["AWS"], "*");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bucket_policy_deserializes_legacy_id() {
|
||||
let legacy_policy = br#"{"ID":"","Version":"2012-10-17","Statement":[{"Sid":"","Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:GetObject"],"NotAction":[],"Resource":["arn:aws:s3:::bucket/*"],"NotResource":[],"Condition":{}}]}"#;
|
||||
|
||||
let policy: BucketPolicy =
|
||||
serde_json::from_slice(legacy_policy).expect("bucket policy with legacy ID should deserialize");
|
||||
assert!(policy.id.is_empty());
|
||||
policy.is_valid().expect("legacy bucket policy should remain valid");
|
||||
|
||||
let policy: BucketPolicy = serde_json::from_str(r#"{"ID":"legacy-policy","Version":"2012-10-17","Statement":[]}"#)
|
||||
.expect("non-empty legacy ID should deserialize");
|
||||
assert_eq!(policy.id.0, "legacy-policy");
|
||||
|
||||
let serialized = serde_json::to_value(&policy).expect("bucket policy should serialize");
|
||||
assert_eq!(serialized["Id"], "legacy-policy");
|
||||
assert!(serialized.get("ID").is_none(), "legacy ID spelling should not be serialized");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bucket_policy_legacy_id_alias_remains_strict() {
|
||||
let unknown_field = r#"{"Version":"2012-10-17","Statement":[],"Unexpected":true}"#;
|
||||
let error =
|
||||
serde_json::from_str::<BucketPolicy>(unknown_field).expect_err("unrelated unknown fields should remain rejected");
|
||||
assert!(
|
||||
error.to_string().contains("unknown field `Unexpected`"),
|
||||
"unexpected deserialization error: {error}"
|
||||
);
|
||||
|
||||
let duplicate_id = r#"{"Id":"current-policy","ID":"legacy-policy","Version":"2012-10-17","Statement":[]}"#;
|
||||
let error = serde_json::from_str::<BucketPolicy>(duplicate_id)
|
||||
.expect_err("canonical and legacy ID fields should not be accepted together");
|
||||
assert!(
|
||||
error.to_string().contains("duplicate field `Id`"),
|
||||
"unexpected deserialization error: {error}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_existing_object_tag_condition_helpers() {
|
||||
let identity_policy = Policy::parse_config(
|
||||
|
||||
Reference in New Issue
Block a user