Compare commits

..

1 commit

Author SHA1 Message Date
2380745185 sse-c: use different object encryption key for each object
All checks were successful
ci/woodpecker/pr/debug Pipeline was successful
ci/woodpecker/push/debug Pipeline was successful
2025-03-18 16:05:39 +01:00
3 changed files with 18 additions and 22 deletions

View file

@ -363,7 +363,7 @@ pub async fn handle_upload_part_copy(
let dest_upload_id = multipart::decode_upload_id(upload_id)?;
let dest_key = dest_key.to_string();
let (source_object, (_, dest_version, mut dest_mpu)) = futures::try_join!(
let (source_object, (dest_object, dest_version, mut dest_mpu)) = futures::try_join!(
get_copy_source(&ctx, req),
multipart::get_upload(&ctx, &dest_key, &dest_upload_id)
)?;
@ -383,6 +383,8 @@ pub async fn handle_upload_part_copy(
&source_version_meta.encryption,
OekDerivationInfo::for_object(&source_object, source_object_version),
)?;
let dest_oek_params = OekDerivationInfo::for_object(&dest_object, &dest_version);
let (dest_object_encryption, dest_object_checksum_algorithm) = match dest_version.state {
ObjectVersionState::Uploading {
encryption,
@ -395,11 +397,7 @@ pub async fn handle_upload_part_copy(
&garage,
req.headers(),
&dest_object_encryption,
OekDerivationInfo {
bucket_id: ctx.bucket_id,
version_id: dest_upload_id,
object_key: &dest_key,
},
dest_oek_params,
)?;
let same_encryption = EncryptionParams::is_same(&source_encryption, &dest_encryption);

View file

@ -409,6 +409,13 @@ impl EncryptionParams {
}
}
pub fn has_encryption_header(headers: &HeaderMap) -> bool {
match headers.get(X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM) {
Some(h) => h.as_bytes() == CUSTOMER_ALGORITHM_AES256,
None => false,
}
}
fn parse_request_headers(
headers: &HeaderMap,
alg_header: &HeaderName,
@ -469,7 +476,7 @@ fn parse_request_headers(
}
impl<'a> OekDerivationInfo<'a> {
pub fn for_object(object: &'a Object, version: &'a ObjectVersion) -> Self {
pub fn for_object<'b>(object: &'a Object, version: &'b ObjectVersion) -> Self {
Self {
bucket_id: object.bucket_id,
version_id: version.uuid,

View file

@ -26,7 +26,7 @@ use garage_api_common::helpers::*;
use garage_api_common::signature::checksum::*;
use crate::api_server::{ReqBody, ResBody};
use crate::encryption::{EncryptionParams, OekDerivationInfo};
use crate::encryption::{has_encryption_header, EncryptionParams, OekDerivationInfo};
use crate::error::*;
use crate::put::*;
use crate::xml as s3_xml;
@ -126,16 +126,9 @@ pub async fn handle_put_part(
let (req_head, mut req_body) = req.into_parts();
let oek_params = OekDerivationInfo {
bucket_id: ctx.bucket_id,
version_id: upload_id,
object_key: &key,
};
// Before we stream the body, configure the needed checksums.
req_body.add_expected_checksums(expected_checksums.clone());
// TODO: avoid parsing encryption headers twice...
if !EncryptionParams::new_from_headers(&garage, &req_head.headers, oek_params)?.is_encrypted() {
if !has_encryption_header(&req_head.headers) {
// For non-encrypted objects, we need to compute the md5sum in all cases
// (even if content-md5 is not set), because it is used as an etag of the
// part, which is in turn used in the etag computation of the whole object
@ -148,10 +141,11 @@ pub async fn handle_put_part(
let mut chunker = StreamChunker::new(stream, garage.config.block_size);
// Read first chuck, and at the same time try to get object to see if it exists
let ((_, object_version, mut mpu), first_block) =
let ((object, object_version, mut mpu), first_block) =
futures::try_join!(get_upload(&ctx, &key, &upload_id), chunker.next(),)?;
// Check encryption params
let oek_params = OekDerivationInfo::for_object(&object, &object_version);
let (object_encryption, checksum_algorithm) = match object_version.state {
ObjectVersionState::Uploading {
encryption,
@ -315,6 +309,7 @@ pub async fn handle_complete_multipart_upload(
return Err(Error::bad_request("No data was uploaded"));
}
let oek_params = OekDerivationInfo::for_object(&object, &object_version);
let (object_encryption, checksum_algorithm) = match object_version.state {
ObjectVersionState::Uploading {
encryption,
@ -439,11 +434,7 @@ pub async fn handle_complete_multipart_upload(
&garage,
&req_head.headers,
&object_encryption,
OekDerivationInfo {
bucket_id: *bucket_id,
version_id: upload_id,
object_key: &key,
},
oek_params,
)?;
let new_meta = ObjectVersionMetaInner {
headers: meta.into_owned().headers,