mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +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 {
|
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 {
|
pub fn table_bucket_enabled(&self) -> bool {
|
||||||
@@ -1113,6 +1113,24 @@ mod test {
|
|||||||
assert_eq!(bm.name, new.name);
|
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]
|
#[test]
|
||||||
fn parse_all_configs_parses_stored_configs_without_store_dependency() {
|
fn parse_all_configs_parses_stored_configs_without_store_dependency() {
|
||||||
let mut bm = BucketMetadata::new("test-bucket");
|
let mut bm = BucketMetadata::new("test-bucket");
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
// Performance metrics recording (with zero-copy-metrics integration)
|
// Performance metrics recording (with zero-copy-metrics integration)
|
||||||
use rustfs_io_metrics::buffered_write;
|
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::ECStore;
|
||||||
use super::storage_api::object_usecase::access::{
|
use super::storage_api::object_usecase::access::{
|
||||||
PostObjectRequestMarker, authorize_request, has_bypass_governance_header, req_info_mut,
|
PostObjectRequestMarker, authorize_request, has_bypass_governance_header, req_info_mut,
|
||||||
@@ -35,7 +37,7 @@ use super::storage_api::object_usecase::bucket::{
|
|||||||
metadata_sys,
|
metadata_sys,
|
||||||
object_lock::{
|
object_lock::{
|
||||||
objectlock::{get_object_legalhold_meta, get_object_retention_meta},
|
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,
|
predict_lifecycle_expiration,
|
||||||
quota::QuotaOperation,
|
quota::QuotaOperation,
|
||||||
@@ -5053,8 +5055,7 @@ impl DefaultObjectUsecase {
|
|||||||
});
|
});
|
||||||
let force_delete = opts.delete_prefix;
|
let force_delete = opts.delete_prefix;
|
||||||
|
|
||||||
let lock_cfg = BucketObjectLockSys::get(&bucket).await;
|
if opts.delete_prefix && bucket_object_locking_enabled(&bucket).await {
|
||||||
if lock_cfg.is_some() && opts.delete_prefix {
|
|
||||||
return Err(S3Error::with_message(
|
return Err(S3Error::with_message(
|
||||||
S3ErrorCode::Custom("force-delete is forbidden on Object Locking enabled buckets".into()),
|
S3ErrorCode::Custom("force-delete is forbidden on Object Locking enabled buckets".into()),
|
||||||
"force-delete is forbidden on Object Locking enabled buckets",
|
"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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -567,8 +567,6 @@ pub(crate) mod bucket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod objectlock_sys {
|
pub(crate) mod objectlock_sys {
|
||||||
pub(crate) type BucketObjectLockSys =
|
|
||||||
crate::storage::storage_api::ecstore_bucket::object_lock::objectlock_sys::BucketObjectLockSys;
|
|
||||||
pub(crate) type ObjectLockBlockReason =
|
pub(crate) type ObjectLockBlockReason =
|
||||||
crate::storage::storage_api::ecstore_bucket::object_lock::objectlock_sys::ObjectLockBlockReason;
|
crate::storage::storage_api::ecstore_bucket::object_lock::objectlock_sys::ObjectLockBlockReason;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user