mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
fix: block force delete on object lock buckets (#4298)
This commit is contained in:
@@ -423,7 +423,7 @@ impl BucketMetadata {
|
||||
}
|
||||
|
||||
pub fn object_locking(&self) -> bool {
|
||||
self.lock_enabled || (self.versioning_config.as_ref().is_some_and(|v| v.enabled()))
|
||||
self.lock_enabled || self.object_lock_config.as_ref().is_some_and(|v| v.enabled())
|
||||
}
|
||||
|
||||
pub fn table_bucket_enabled(&self) -> bool {
|
||||
@@ -1113,6 +1113,24 @@ mod test {
|
||||
assert_eq!(bm.name, new.name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_locking_requires_lock_metadata_not_plain_versioning() {
|
||||
use s3s::dto::ObjectLockEnabled;
|
||||
|
||||
let mut bm = BucketMetadata::new("test-bucket");
|
||||
bm.versioning_config = Some(VersioningConfiguration {
|
||||
status: Some(s3s::dto::BucketVersioningStatus::from_static("Enabled")),
|
||||
..Default::default()
|
||||
});
|
||||
assert!(!bm.object_locking());
|
||||
|
||||
bm.object_lock_config = Some(ObjectLockConfiguration {
|
||||
object_lock_enabled: Some(ObjectLockEnabled::from_static(ObjectLockEnabled::ENABLED)),
|
||||
..Default::default()
|
||||
});
|
||||
assert!(bm.object_locking());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_all_configs_parses_stored_configs_without_store_dependency() {
|
||||
let mut bm = BucketMetadata::new("test-bucket");
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// Performance metrics recording (with zero-copy-metrics integration)
|
||||
use rustfs_io_metrics::buffered_write;
|
||||
|
||||
use crate::storage_api::table::get_bucket_metadata;
|
||||
|
||||
use super::storage_api::object_usecase::ECStore;
|
||||
use super::storage_api::object_usecase::access::{
|
||||
PostObjectRequestMarker, authorize_request, has_bypass_governance_header, req_info_mut,
|
||||
@@ -35,7 +37,7 @@ use super::storage_api::object_usecase::bucket::{
|
||||
metadata_sys,
|
||||
object_lock::{
|
||||
objectlock::{get_object_legalhold_meta, get_object_retention_meta},
|
||||
objectlock_sys::{BucketObjectLockSys, check_object_lock_for_deletion, is_retention_active},
|
||||
objectlock_sys::{check_object_lock_for_deletion, is_retention_active},
|
||||
},
|
||||
predict_lifecycle_expiration,
|
||||
quota::QuotaOperation,
|
||||
@@ -5053,8 +5055,7 @@ impl DefaultObjectUsecase {
|
||||
});
|
||||
let force_delete = opts.delete_prefix;
|
||||
|
||||
let lock_cfg = BucketObjectLockSys::get(&bucket).await;
|
||||
if lock_cfg.is_some() && opts.delete_prefix {
|
||||
if opts.delete_prefix && bucket_object_locking_enabled(&bucket).await {
|
||||
return Err(S3Error::with_message(
|
||||
S3ErrorCode::Custom("force-delete is forbidden on Object Locking enabled buckets".into()),
|
||||
"force-delete is forbidden on Object Locking enabled buckets",
|
||||
@@ -6265,6 +6266,12 @@ fn object_attributes_requested(object_attributes: &[ObjectAttributes], name: &'s
|
||||
})
|
||||
}
|
||||
|
||||
async fn bucket_object_locking_enabled(bucket: &str) -> bool {
|
||||
get_bucket_metadata(bucket)
|
||||
.await
|
||||
.is_ok_and(|metadata| metadata.object_locking())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -567,8 +567,6 @@ pub(crate) mod bucket {
|
||||
}
|
||||
|
||||
pub(crate) mod objectlock_sys {
|
||||
pub(crate) type BucketObjectLockSys =
|
||||
crate::storage::storage_api::ecstore_bucket::object_lock::objectlock_sys::BucketObjectLockSys;
|
||||
pub(crate) type ObjectLockBlockReason =
|
||||
crate::storage::storage_api::ecstore_bucket::object_lock::objectlock_sys::ObjectLockBlockReason;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user