fix: restore default CORS fallback and STS object ACL ownership (#2053)

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
安正超
2026-03-03 01:08:50 +08:00
committed by GitHub
parent fff96a0921
commit 08e1f4670b
13 changed files with 798 additions and 1105 deletions
+10 -127
View File
@@ -17,7 +17,7 @@
use crate::app::context::{AppContext, default_notify_interface, get_global_app_context};
use crate::config::workload_profiles::RustFSBufferConfig;
use crate::error::ApiError;
use crate::storage::access::{ReqInfo, authorize_request, has_bypass_governance_header, req_info_mut};
use crate::storage::access::{authorize_request, has_bypass_governance_header, req_info_mut};
use crate::storage::concurrency::{
CachedGetObject, ConcurrencyManager, GetObjectGuard, get_concurrency_aware_buffer_size, get_concurrency_manager,
};
@@ -29,7 +29,7 @@ use crate::storage::options::{
filter_object_metadata, get_content_sha256_with_query, get_opts, put_opts,
};
use crate::storage::s3_api::multipart::parse_list_parts_params;
use crate::storage::s3_api::{restore, select};
use crate::storage::s3_api::{acl, restore, select};
use crate::storage::*;
use bytes::Bytes;
use datafusion::arrow::{
@@ -287,11 +287,6 @@ impl DefaultObjectUsecase {
body,
bucket,
key,
acl,
grant_full_control,
grant_read,
grant_read_acp,
grant_write_acp,
content_length,
content_type,
tagging,
@@ -318,14 +313,6 @@ impl DefaultObjectUsecase {
// Validate object key
validate_object_key(&key, "PUT")?;
if let Some(acl) = &acl
&& let Ok((config, _)) = metadata_sys::get_public_access_block_config(&bucket).await
&& config.block_public_acls.unwrap_or(false)
&& is_public_canned_acl(acl.as_str())
{
return Err(s3_error!(AccessDenied, "Access Denied"));
}
if let Some(size) = content_length {
self.check_bucket_quota(&bucket, QuotaOperation::PutObject, size as u64)
.await?;
@@ -407,33 +394,6 @@ impl DefaultObjectUsecase {
)?;
let mut metadata = metadata.unwrap_or_default();
let owner = req
.extensions
.get::<ReqInfo>()
.and_then(|info| info.cred.as_ref())
.map(|cred| owner_from_access_key(&cred.access_key))
.unwrap_or_else(default_owner);
let bucket_owner = default_owner();
let mut stored_acl = stored_acl_from_grant_headers(
&owner,
grant_read.map(|v| v.to_string()),
None,
grant_read_acp.map(|v| v.to_string()),
grant_write_acp.map(|v| v.to_string()),
grant_full_control.map(|v| v.to_string()),
)?;
if stored_acl.is_none()
&& let Some(canned) = acl.as_ref()
{
stored_acl = Some(stored_acl_from_canned_object(canned.as_str(), &bucket_owner, &owner));
}
let stored_acl =
stored_acl.unwrap_or_else(|| stored_acl_from_canned_object(ObjectCannedACL::PRIVATE, &bucket_owner, &owner));
let acl_data = serialize_acl(&stored_acl)?;
metadata.insert(INTERNAL_ACL_METADATA_KEY.to_string(), String::from_utf8_lossy(&acl_data).to_string());
if let Some(content_type) = content_type {
metadata.insert("content-type".to_string(), content_type.to_string());
}
@@ -622,13 +582,7 @@ impl DefaultObjectUsecase {
let PutObjectAclInput {
bucket,
key,
acl,
access_control_policy,
grant_full_control,
grant_read,
grant_read_acp,
grant_write,
grant_write_acp,
version_id,
..
} = req.input;
@@ -640,64 +594,15 @@ impl DefaultObjectUsecase {
let opts: ObjectOptions = get_opts(&bucket, &key, version_id.clone(), None, &req.headers)
.await
.map_err(ApiError::from)?;
let info = store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
let bucket_owner = default_owner();
let existing_owner = info
.user_defined
.get(INTERNAL_ACL_METADATA_KEY)
.and_then(|acl| serde_json::from_str::<StoredAcl>(acl).ok())
.map(|acl| acl.owner)
.unwrap_or_else(|| bucket_owner.clone());
let mut stored_acl = access_control_policy
.as_ref()
.map(|policy| stored_acl_from_policy(policy, &existing_owner))
.transpose()?;
if stored_acl.is_none() {
stored_acl = stored_acl_from_grant_headers(
&existing_owner,
grant_read.map(|v| v.to_string()),
grant_write.map(|v| v.to_string()),
grant_read_acp.map(|v| v.to_string()),
grant_write_acp.map(|v| v.to_string()),
grant_full_control.map(|v| v.to_string()),
)?;
if access_control_policy.is_some() {
return Err(s3_error!(
NotImplemented,
"ACL XML grants are not supported; use canned ACL headers or omit ACL"
));
}
if stored_acl.is_none()
&& let Some(canned) = acl
{
stored_acl = Some(stored_acl_from_canned_object(canned.as_str(), &bucket_owner, &existing_owner));
}
let stored_acl =
stored_acl.unwrap_or_else(|| stored_acl_from_canned_object(ObjectCannedACL::PRIVATE, &bucket_owner, &existing_owner));
if let Ok((config, _)) = metadata_sys::get_public_access_block_config(&bucket).await
&& config.block_public_acls.unwrap_or(false)
&& stored_acl.grants.iter().any(is_public_grant)
{
return Err(s3_error!(AccessDenied, "Access Denied"));
}
let acl_data = serialize_acl(&stored_acl)?;
let mut eval_metadata = HashMap::new();
eval_metadata.insert(INTERNAL_ACL_METADATA_KEY.to_string(), String::from_utf8_lossy(&acl_data).to_string());
let popts = ObjectOptions {
mod_time: info.mod_time,
version_id: opts.version_id,
eval_metadata: Some(eval_metadata),
..Default::default()
};
store.put_object_metadata(&bucket, &key, &popts).await.map_err(|e| {
error!("put_object_metadata failed, {}", e.to_string());
s3_error!(InternalError, "{}", e.to_string())
})?;
Ok(S3Response::new(PutObjectAclOutput::default()))
}
@@ -1606,31 +1511,9 @@ impl DefaultObjectUsecase {
let opts: ObjectOptions = get_opts(&bucket, &key, version_id.clone(), None, &req.headers)
.await
.map_err(ApiError::from)?;
let info = store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
let bucket_owner = default_owner();
let object_owner = info
.user_defined
.get(INTERNAL_ACL_METADATA_KEY)
.and_then(|acl| serde_json::from_str::<StoredAcl>(acl).ok())
.map(|acl| acl.owner)
.unwrap_or_else(default_owner);
let stored_acl = info
.user_defined
.get(INTERNAL_ACL_METADATA_KEY)
.map(|acl| parse_acl_json_or_canned_object(acl, &bucket_owner, &object_owner))
.unwrap_or_else(|| stored_acl_from_canned_object(ObjectCannedACL::PRIVATE, &bucket_owner, &object_owner));
let mut sorted_grants = stored_acl.grants.clone();
sorted_grants.sort_by_key(|grant| grant.grantee.grantee_type != "Group");
let grants = sorted_grants.iter().map(stored_grant_to_dto).collect();
Ok(S3Response::new(GetObjectAclOutput {
grants: Some(grants),
owner: Some(stored_owner_to_dto(&stored_acl.owner)),
..Default::default()
}))
Ok(S3Response::new(acl::build_get_object_acl_output()))
}
pub async fn execute_get_object_attributes(