mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-05 21:07:43 +00:00
fix(storage): restore legacy SSE-S3 read compatibility (#3584)
* Update .gitignore * Fix. fixed SSE-S3 compatibility issues in large-scale testing * fix * fix(ecstore): reject whitespace bucket names * Update replication_extension_test.rs * style(ecstore): format bucket whitespace test --------- Co-authored-by: houseme <housemecn@gmail.com> Co-authored-by: cxymds <cxymds@gmail.com>
This commit is contained in:
@@ -1680,10 +1680,22 @@ async fn apply_managed_decryption_material(
|
||||
|
||||
// Use factory pattern to get provider (test or production mode)
|
||||
let provider = get_sse_dek_provider().await?;
|
||||
#[cfg(feature = "rio-v2")]
|
||||
let decrypted_data_key = if is_legacy_rustfs_managed_metadata(&normalized_metadata) {
|
||||
provider
|
||||
.decrypt_legacy_sse_dek(&encrypted_data_key, &kms_key_id, &object_context)
|
||||
.await
|
||||
} else {
|
||||
provider
|
||||
.decrypt_sse_dek(&encrypted_data_key, &kms_key_id, &object_context)
|
||||
.await
|
||||
};
|
||||
#[cfg(not(feature = "rio-v2"))]
|
||||
let decrypted_data_key = provider
|
||||
.decrypt_sse_dek(&encrypted_data_key, &kms_key_id, &object_context)
|
||||
.await
|
||||
.map_err(|e| ApiError::from(StorageError::other(format!("Failed to decrypt data key: {e}"))))?;
|
||||
.await;
|
||||
let decrypted_data_key =
|
||||
decrypted_data_key.map_err(|e| ApiError::from(StorageError::other(format!("Failed to decrypt data key: {e}"))))?;
|
||||
#[cfg(feature = "rio-v2")]
|
||||
let (key_bytes, base_nonce, key_kind) = if let Some(sealed_key) = minio_sealed_key {
|
||||
(
|
||||
@@ -1761,6 +1773,17 @@ pub trait SseDekProvider: Send + Sync {
|
||||
kms_key_id: &str,
|
||||
context: &ObjectEncryptionContext,
|
||||
) -> Result<[u8; 32], ApiError>;
|
||||
|
||||
/// Decrypt a DEK from positively identified legacy managed metadata.
|
||||
#[cfg(feature = "rio-v2")]
|
||||
async fn decrypt_legacy_sse_dek(
|
||||
&self,
|
||||
encrypted_dek: &[u8],
|
||||
kms_key_id: &str,
|
||||
context: &ObjectEncryptionContext,
|
||||
) -> Result<[u8; 32], ApiError> {
|
||||
self.decrypt_sse_dek(encrypted_dek, kms_key_id, context).await
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -1820,6 +1843,24 @@ impl SseDekProvider for KmsSseDekProvider {
|
||||
|
||||
Ok(data_key.plaintext_key)
|
||||
}
|
||||
|
||||
#[cfg(feature = "rio-v2")]
|
||||
async fn decrypt_legacy_sse_dek(
|
||||
&self,
|
||||
encrypted_dek: &[u8],
|
||||
_kms_key_id: &str,
|
||||
_context: &ObjectEncryptionContext,
|
||||
) -> Result<[u8; 32], ApiError> {
|
||||
let service = Self::current_service()
|
||||
.await
|
||||
.ok_or_else(|| ApiError::from(StorageError::other("KMS encryption service is not initialized")))?;
|
||||
let data_key = service
|
||||
.decrypt_legacy_data_key(encrypted_dek)
|
||||
.await
|
||||
.map_err(|e| ApiError::from(StorageError::other(format!("Failed to decrypt legacy data key: {e}"))))?;
|
||||
|
||||
Ok(data_key.plaintext_key)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -2139,6 +2180,14 @@ fn contains_managed_encryption_metadata(metadata: &HashMap<String, String>) -> b
|
||||
|| metadata.contains_key(MINIO_INTERNAL_ENCRYPTION_KMS_CONTEXT_HEADER)
|
||||
}
|
||||
|
||||
#[cfg(feature = "rio-v2")]
|
||||
fn is_legacy_rustfs_managed_metadata(metadata: &HashMap<String, String>) -> bool {
|
||||
metadata.contains_key(INTERNAL_ENCRYPTION_KEY_HEADER)
|
||||
&& metadata.contains_key(INTERNAL_ENCRYPTION_IV_HEADER)
|
||||
&& !metadata.contains_key(MINIO_INTERNAL_ENCRYPTION_S3_SEALED_KEY_HEADER)
|
||||
&& !metadata.contains_key(MINIO_INTERNAL_ENCRYPTION_KMS_SEALED_KEY_HEADER)
|
||||
}
|
||||
|
||||
#[cfg(feature = "rio-v2")]
|
||||
fn parse_minio_managed_sealed_key(
|
||||
metadata: &HashMap<String, String>,
|
||||
@@ -3047,6 +3096,23 @@ mod tests {
|
||||
assert!(metadata.contains_key("content-type"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "rio-v2")]
|
||||
#[test]
|
||||
fn test_legacy_managed_metadata_excludes_sealed_keys() {
|
||||
let legacy_metadata = HashMap::from([
|
||||
(INTERNAL_ENCRYPTION_KEY_HEADER.to_string(), "encrypted-dek".to_string()),
|
||||
(INTERNAL_ENCRYPTION_IV_HEADER.to_string(), "nonce".to_string()),
|
||||
]);
|
||||
assert!(is_legacy_rustfs_managed_metadata(&legacy_metadata));
|
||||
|
||||
let sealed_metadata = HashMap::from([
|
||||
(INTERNAL_ENCRYPTION_KEY_HEADER.to_string(), "encrypted-dek".to_string()),
|
||||
(INTERNAL_ENCRYPTION_IV_HEADER.to_string(), "nonce".to_string()),
|
||||
(MINIO_INTERNAL_ENCRYPTION_S3_SEALED_KEY_HEADER.to_string(), "sealed-key".to_string()),
|
||||
]);
|
||||
assert!(!is_legacy_rustfs_managed_metadata(&sealed_metadata));
|
||||
}
|
||||
|
||||
#[cfg(feature = "rio-v2")]
|
||||
#[test]
|
||||
fn test_normalize_managed_metadata_accepts_minio_only_headers() {
|
||||
|
||||
Reference in New Issue
Block a user