shashank created CAMEL-25903:
--------------------------------

             Summary: camel-aws2-s3 - with multiPartUpload=true, an object 
uploaded in parts is stored without the user metadata of the CamelAwsS3Metadata 
header
                 Key: CAMEL-25903
                 URL: https://issues.apache.org/jira/browse/CAMEL-25903
             Project: Camel
          Issue Type: Bug
          Components: camel-aws2-s3
            Reporter: shashank
            Assignee: shashank


With {{multiPartUpload=true}}, {{AWS2S3Producer.processMultiPart}} (main 
74ee085f7d64, lines 172-347) uploads a body that is at least {{partSize}} long 
(default 25 MB) with {{CreateMultipartUpload}} / {{UploadPart}} / 
{{CompleteMultipartUpload}}, and a smaller body with a single {{PutObject}} 
({{doPutObject}}). Both start from the same user metadata, computed from the 
{{CamelAwsS3Metadata}} header:

{code:java}
Map<String, String> objectMetadata = determineMetadata(exchange);
...
objectMetadata.put("Content-Length", "" + contentLength);
...
CreateMultipartUploadRequest.Builder createMultipartUploadRequest
        = 
CreateMultipartUploadRequest.builder().bucket(bucketName).key(keyName);
{code}

{{doPutObject}} sets it on the request 
({{putObjectRequest...metadata(objectMetadata)}}), but the multipart path never 
puts the map on the {{CreateMultipartUploadRequest}}: an object uploaded in 
parts is stored without any user metadata. The upload succeeds and nothing is 
logged. Storage class, ACL, content type, cache control, content disposition, 
content encoding and the encryption options are all applied on that path; only 
the metadata is left out.

So with {{multiPartUpload=true}} whether an object gets its metadata depends on 
its size. The S3 consumer sets {{CamelAwsS3Metadata}} to the user metadata of 
the object it read, so a route that copies objects from one bucket to another 
with multipart upload keeps the metadata of the small objects and silently 
drops it for the large ones. CAMEL-17713 added user metadata to the producer 
for integrations that rely on it; the multipart path has never had it (the same 
lines are in 3.22.x).

*Fix*: {{processMultiPart}} sets the metadata on the 
{{CreateMultipartUploadRequest}}. The {{Content-Length}} entry that the 
multipart path added to the map (never sent anywhere) is removed, so it does 
not become an {{x-amz-meta-content-length}} entry. No option or documentation 
change; no upgrade note (objects now get the metadata the route asked for).

*Tests*: new {{AWS2S3ProducerMultipartMetadataTest}} (2 tests, Mockito 
{{S3Client}} as the other producer tests of the module, {{partSize=5}}). 
{{multipartUploadStoresTheUserMetadata}} (a 12 byte body, 3 parts) fails on 
main with {{expected: {"checksum"="abc123", "origin"="camel"} but was: {}}}. 
{{bodySmallerThanThePartSizeStoresTheUserMetadata}} is a control: the single 
put keeps the metadata on main and with the fix. camel-aws2-s3 unit tests: 118 
run, 0 failures (run with the AWS SDK 2.55.15 jars of the local repository, 
{{-Daws-java-sdk2-version=2.55.15}}; main uses 2.56.0).

*How it was found*: comparing, per producer, the request options applied on 
each code path of one operation (single vs multipart, sync vs async, batch vs 
single). The JUnit tests above are the evidence; nothing was run against AWS S3.

*Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x 
(the same {{CreateMultipartUploadRequest}} without metadata; read, not run).

Not changed, possible follow-ups: with {{useCustomerKey=true}} (SSE-C) the 
{{UploadPartRequest}} of the multipart path does not carry the customer key 
either, which S3 requires for each part, so such uploads fail (loudly).

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to