mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
fix(authz): preserve direct delete usecase callers (#5614)
* fix(authz): preserve direct delete usecase callers * test(ilm): provide owner context for forced deletes
This commit is contained in:
@@ -1495,6 +1495,8 @@ async fn cancelled_transition_waiting_for_prepared_reader_cleans_remote() {
|
|||||||
#[serial]
|
#[serial]
|
||||||
#[ignore = "global-state ILM integration test: runs serialized in the CI ILM Integration (serial) lane, see ci.yml test-ilm-integration-serial and rustfs/backlog#1148 (ilm-1)"]
|
#[ignore = "global-state ILM integration test: runs serialized in the CI ILM Integration (serial) lane, see ci.yml test-ilm-integration-serial and rustfs/backlog#1148 (ilm-1)"]
|
||||||
async fn delete_transitioned_object_removes_remote_tier_copy_via_usecase() {
|
async fn delete_transitioned_object_removes_remote_tier_copy_via_usecase() {
|
||||||
|
use super::storage_api::test::ReqInfo;
|
||||||
|
|
||||||
let (_disk_paths, ecstore) = setup_test_env().await;
|
let (_disk_paths, ecstore) = setup_test_env().await;
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
|
|
||||||
@@ -1531,6 +1533,11 @@ async fn delete_transitioned_object_removes_remote_tier_copy_via_usecase() {
|
|||||||
Method::DELETE,
|
Method::DELETE,
|
||||||
);
|
);
|
||||||
insert_header(&mut req.headers, SUFFIX_FORCE_DELETE, "true");
|
insert_header(&mut req.headers, SUFFIX_FORCE_DELETE, "true");
|
||||||
|
req.extensions.insert(ReqInfo {
|
||||||
|
cred: Some(rustfs_credentials::Credentials::default()),
|
||||||
|
is_owner: true,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
Box::pin(usecase.execute_delete_object(req))
|
Box::pin(usecase.execute_delete_object(req))
|
||||||
.await
|
.await
|
||||||
@@ -1735,6 +1742,8 @@ async fn compensation_driven_complete_multipart_upload_still_transitions() {
|
|||||||
#[serial]
|
#[serial]
|
||||||
#[ignore = "global-state ILM integration test: runs serialized in the CI ILM Integration (serial) lane, see ci.yml test-ilm-integration-serial and rustfs/backlog#1148 (ilm-1)"]
|
#[ignore = "global-state ILM integration test: runs serialized in the CI ILM Integration (serial) lane, see ci.yml test-ilm-integration-serial and rustfs/backlog#1148 (ilm-1)"]
|
||||||
async fn compensation_driven_transition_still_cleans_remote_tier_on_delete() {
|
async fn compensation_driven_transition_still_cleans_remote_tier_on_delete() {
|
||||||
|
use super::storage_api::test::ReqInfo;
|
||||||
|
|
||||||
let (_disk_paths, ecstore) = setup_test_env().await;
|
let (_disk_paths, ecstore) = setup_test_env().await;
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
|
|
||||||
@@ -1771,6 +1780,11 @@ async fn compensation_driven_transition_still_cleans_remote_tier_on_delete() {
|
|||||||
Method::DELETE,
|
Method::DELETE,
|
||||||
);
|
);
|
||||||
insert_header(&mut req.headers, SUFFIX_FORCE_DELETE, "true");
|
insert_header(&mut req.headers, SUFFIX_FORCE_DELETE, "true");
|
||||||
|
req.extensions.insert(ReqInfo {
|
||||||
|
cred: Some(rustfs_credentials::Credentials::default()),
|
||||||
|
is_owner: true,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
Box::pin(usecase.execute_delete_object(req))
|
Box::pin(usecase.execute_delete_object(req))
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -6615,7 +6615,8 @@ impl DefaultObjectUsecase {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !recursive_force_delete_is_authorized(&req.headers, req_info_ref(&req)?.is_owner, false) {
|
let is_owner = req_info_ref(&req).map(|info| info.is_owner).unwrap_or(false);
|
||||||
|
if !recursive_force_delete_is_authorized(&req.headers, is_owner, false) {
|
||||||
return Err(S3Error::with_message(
|
return Err(S3Error::with_message(
|
||||||
S3ErrorCode::AccessDenied,
|
S3ErrorCode::AccessDenied,
|
||||||
"Recursive force-delete is restricted to administrative requests",
|
"Recursive force-delete is restricted to administrative requests",
|
||||||
@@ -7081,7 +7082,7 @@ impl DefaultObjectUsecase {
|
|||||||
authorize_request(&mut req, Action::S3Action(S3Action::ReplicateDeleteAction)).await?;
|
authorize_request(&mut req, Action::S3Action(S3Action::ReplicateDeleteAction)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_owner = req_info_ref(&req)?.is_owner;
|
let is_owner = req_info_ref(&req).map(|info| info.is_owner).unwrap_or(false);
|
||||||
if !recursive_force_delete_is_authorized(&req.headers, is_owner, replica) {
|
if !recursive_force_delete_is_authorized(&req.headers, is_owner, replica) {
|
||||||
return Err(S3Error::with_message(
|
return Err(S3Error::with_message(
|
||||||
S3ErrorCode::AccessDenied,
|
S3ErrorCode::AccessDenied,
|
||||||
@@ -13386,6 +13387,23 @@ mod tests {
|
|||||||
|
|
||||||
let err = usecase.execute_delete_objects(req).await.unwrap_err();
|
let err = usecase.execute_delete_objects(req).await.unwrap_err();
|
||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
|
assert_eq!(err.message(), Some("Not init"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn execute_delete_object_allows_non_force_request_without_req_info_until_store_lookup() {
|
||||||
|
let input = DeleteObjectInput::builder()
|
||||||
|
.bucket("test-bucket".to_string())
|
||||||
|
.key("test-key".to_string())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let err = DefaultObjectUsecase::without_context()
|
||||||
|
.execute_delete_object(build_request(input, Method::DELETE))
|
||||||
|
.await
|
||||||
|
.expect_err("an uninitialized store should be reported after non-force admission");
|
||||||
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
|
assert_eq!(err.message(), Some("Not init"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user