mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-04 20:37:43 +00:00
fix(auth): authorize DeleteObjects per key (#2814)
This commit is contained in:
@@ -3003,6 +3003,19 @@ impl DefaultObjectUsecase {
|
||||
continue;
|
||||
}
|
||||
|
||||
if bypass_governance {
|
||||
let auth_res = authorize_request(&mut req, Action::S3Action(S3Action::BypassGovernanceRetentionAction)).await;
|
||||
if let Err(e) = auth_res {
|
||||
delete_results[idx].error = Some(Error {
|
||||
code: Some("AccessDenied".to_string()),
|
||||
key: Some(obj_id.key.clone()),
|
||||
message: Some(e.to_string()),
|
||||
version_id: version_id.clone(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let mut object = ObjectToDelete {
|
||||
object_name: obj_id.key.clone(),
|
||||
version_id: version_uuid,
|
||||
|
||||
@@ -1069,13 +1069,6 @@ impl S3Access for FS {
|
||||
req_info.object = None;
|
||||
req_info.version_id = None;
|
||||
|
||||
authorize_request(req, Action::S3Action(S3Action::DeleteObjectAction)).await?;
|
||||
|
||||
// S3 Standard: When bypass_governance header is set, must have s3:BypassGovernanceRetention permission
|
||||
if has_bypass_governance_header(&req.headers) {
|
||||
authorize_request(req, Action::S3Action(S3Action::BypassGovernanceRetentionAction)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2401,6 +2394,38 @@ mod tests {
|
||||
assert_eq!(req_info.version_id, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_objects_defers_object_authorization_to_usecase() {
|
||||
let input = DeleteObjectsInput::builder()
|
||||
.bucket("test-bucket".to_string())
|
||||
.delete(Delete {
|
||||
objects: vec![ObjectIdentifier {
|
||||
key: "prefix/test-key".to_string(),
|
||||
version_id: None,
|
||||
..Default::default()
|
||||
}],
|
||||
quiet: None,
|
||||
})
|
||||
.build()
|
||||
.expect("delete objects input should build");
|
||||
|
||||
let mut req = build_request(input, Method::POST);
|
||||
req.extensions.insert(ReqInfo {
|
||||
cred: Some(rustfs_credentials::Credentials::default()),
|
||||
..ReqInfo::default()
|
||||
});
|
||||
|
||||
FS::new()
|
||||
.delete_objects(&mut req)
|
||||
.await
|
||||
.expect("DeleteObjects access hook should not require bucket-level DeleteObject");
|
||||
|
||||
let req_info = req.extensions.get::<ReqInfo>().expect("req info should remain available");
|
||||
assert_eq!(req_info.bucket.as_deref(), Some("test-bucket"));
|
||||
assert_eq!(req_info.object, None);
|
||||
assert_eq!(req_info.version_id, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn abort_multipart_upload_rejects_unauthorized_request() {
|
||||
let fs = FS::new();
|
||||
|
||||
Reference in New Issue
Block a user