mod common;
use bucketwarden_lock::ObjectLock;
use bucketwarden_s3::{
ObjectMetadata, ObjectTaggingRequest, PutObjectRequest, ReplicationRule, ServerSideEncryption,
};
use bucketwarden_server::RuntimeError;
use common::*;
use std::collections::BTreeMap;
#[test]
fn replication_preserves_metadata_and_skips_encrypted_versions_when_disabled() {
let mut runtime = runtime();
runtime
.create_bucket("alice", "archive-001")
.expect("source");
runtime
.create_bucket("alice", "archive-002")
.expect("destination");
runtime
.put_bucket_replication(
"alice",
"archive-001",
Some("arn:aws:iam::123456789012:role/bucketwarden-replication".to_string()),
vec![ReplicationRule {
id: "records".to_string(),
status: "Enabled".to_string(),
destination_bucket: "arn:aws:s3:::archive-002".to_string(),
prefix: Some("records/".to_string()),
tag_filter: BTreeMap::new(),
delete_marker_replication: false,
existing_object_replication: false,
replicate_encrypted_objects: false,
}],
)
.expect("replication config");
let plain = runtime
.put_object(
"alice",
PutObjectRequest {
bucket: "archive-001".to_string(),
key: "records/plain.json".to_string(),
body: br#"{"plain":true}"#.to_vec(),
metadata: ObjectMetadata {
content_type: "application/json".to_string(),
content_encoding: None,
user_metadata: BTreeMap::from([("owner".to_string(), "team-a".to_string())]),
encryption: None,
},
},
ObjectLock::none(),
)
.expect("plain");
runtime
.put_object_tagging(
"alice",
ObjectTaggingRequest {
bucket: "archive-001".to_string(),
key: "records/plain.json".to_string(),
version_id: Some(plain.version_id.clone()),
tags: BTreeMap::from([("class".to_string(), "regulated".to_string())]),
},
)
.expect("tag plain");
let encrypted = runtime
.put_object(
"alice",
PutObjectRequest {
bucket: "archive-001".to_string(),
key: "records/secret.json".to_string(),
body: br#"{"secret":true}"#.to_vec(),
metadata: ObjectMetadata {
content_type: "application/json".to_string(),
content_encoding: None,
user_metadata: BTreeMap::new(),
encryption: Some(ServerSideEncryption {
algorithm: "aws:kms".to_string(),
kms_key_id: Some("local-dev".to_string()),
}),
},
},
ObjectLock::none(),
)
.expect("encrypted");
let run = runtime
.run_bucket_replication("alice", "archive-001")
.expect("replicate");
assert_eq!(run.replicated_object_versions, 1);
assert_eq!(run.skipped_encrypted_objects, 1);
let replicated = runtime
.get_object_version(
"alice",
"archive-002",
"records/plain.json",
&plain.version_id,
)
.expect("replicated plain");
assert_eq!(replicated.body, br#"{"plain":true}"#);
assert_eq!(replicated.metadata.content_type, "application/json");
assert_eq!(
replicated.metadata.user_metadata.get("owner"),
Some(&"team-a".to_string())
);
let replicated_tags = runtime
.get_object_tagging(
"alice",
"archive-002",
"records/plain.json",
Some(&plain.version_id),
)
.expect("replicated tags");
assert_eq!(
replicated_tags.tags.get("class"),
Some(&"regulated".to_string())
);
assert!(matches!(
runtime.get_object_version(
"alice",
"archive-002",
"records/secret.json",
&encrypted.version_id
),
Err(RuntimeError::NoSuchVersion { .. }) | Err(RuntimeError::NoSuchKey(_))
));
}