This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.22.x by this push:
     new 072844868ecf [backport camel-4.22.x] CAMEL-26336: camel-minio: 
MinioProducer should apply configured server-side encryption options (#28615)
072844868ecf is described below

commit 072844868ecf0a5f309ec270fa57a3ce4f979f87
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Oct 28 21:50:25 2026 +0100

    [backport camel-4.22.x] CAMEL-26336: camel-minio: MinioProducer should 
apply configured server-side encryption options (#28615)
    
    * [backport camel-4.22.x] CAMEL-26336: camel-minio: MinioProducer should 
apply configured server-side encryption options
    
    (cherry picked from commit b9b931f9f5522dd8d61ad9ded50510c065fe6965)
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * CAMEL-26336: camel-minio - adapt the encryption test to the operations of 
camel-4.22.x
    
    The test sent MinioOperations.getObjectRange, which exists only on main
    (CAMEL-25933 renamed getPartialObject to getObjectRange). On this branch
    the operation is getPartialObject, which reaches the same producer method.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .../camel/component/minio/MinioProducer.java       |  48 ++++-
 .../minio/MinioProducerEncryptionTest.java         | 240 +++++++++++++++++++++
 2 files changed, 282 insertions(+), 6 deletions(-)

diff --git 
a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
 
b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
index 9b9d926883a9..d95a2636226f 100644
--- 
a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
+++ 
b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
@@ -67,6 +67,16 @@ public class MinioProducer extends DefaultProducer {
         super(endpoint);
     }
 
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        if (getConfiguration().getServerSideEncryption() != null
+                && getConfiguration().getServerSideEncryptionCustomerKey() != 
null) {
+            throw new IllegalArgumentException(
+                    "Only one of serverSideEncryption or 
serverSideEncryptionCustomerKey can be configured");
+        }
+    }
+
     public static Message getMessageForResponse(final Exchange exchange) {
         return exchange.getMessage();
     }
@@ -195,6 +205,12 @@ public class MinioProducer extends DefaultProducer {
                 .object(objectName)
                 .userMetadata(objectMetadata);
 
+        if (getConfiguration().getServerSideEncryptionCustomerKey() != null) {
+            
putObjectRequest.sse(getConfiguration().getServerSideEncryptionCustomerKey());
+        } else if (getConfiguration().getServerSideEncryption() != null) {
+            putObjectRequest.sse(getConfiguration().getServerSideEncryption());
+        }
+
         if (!extraHeaders.isEmpty()) {
             putObjectRequest.extraHeaders(extraHeaders);
         }
@@ -255,11 +271,21 @@ public class MinioProducer extends DefaultProducer {
                     .bucket(bucketName)
                     .object(sourceKey);
 
+            if (getConfiguration().getServerSideEncryptionCustomerKey() != 
null) {
+                
copySourceBuilder.ssec(getConfiguration().getServerSideEncryptionCustomerKey());
+            }
+
             CopyObjectArgs.Builder copyObjectRequest = CopyObjectArgs.builder()
                     .bucket(destinationBucketName)
                     .object(destinationKey)
                     .source(copySourceBuilder.build());
 
+            if (getConfiguration().getServerSideEncryptionCustomerKey() != 
null) {
+                
copyObjectRequest.sse(getConfiguration().getServerSideEncryptionCustomerKey());
+            } else if (getConfiguration().getServerSideEncryption() != null) {
+                
copyObjectRequest.sse(getConfiguration().getServerSideEncryption());
+            }
+
             ObjectWriteResponse copyObjectResult = 
minioClient.copyObject(copyObjectRequest.build());
 
             Message message = getMessageForResponse(exchange);
@@ -340,10 +366,15 @@ public class MinioProducer extends DefaultProducer {
             final String bucketName = determineBucketName(exchange);
             final String sourceKey = determineObjectName(exchange);
 
-            InputStream respond = minioClient.getObject(GetObjectArgs.builder()
+            GetObjectArgs.Builder getObjectRequest = GetObjectArgs.builder()
                     .bucket(bucketName)
-                    .object(sourceKey)
-                    .build());
+                    .object(sourceKey);
+
+            if (getConfiguration().getServerSideEncryptionCustomerKey() != 
null) {
+                
getObjectRequest.ssec(getConfiguration().getServerSideEncryptionCustomerKey());
+            }
+
+            InputStream respond = 
minioClient.getObject(getObjectRequest.build());
 
             Message message = getMessageForResponse(exchange);
             message.setBody(respond);
@@ -370,12 +401,17 @@ public class MinioProducer extends DefaultProducer {
                         "A Offset and length header must be configured to 
perform a partial get operation.");
             }
 
-            InputStream respond = minioClient.getObject(GetObjectArgs.builder()
+            GetObjectArgs.Builder getObjectRequest = GetObjectArgs.builder()
                     .bucket(bucketName)
                     .object(sourceKey)
                     .offset(Long.parseLong(offset))
-                    .length(Long.parseLong(length))
-                    .build());
+                    .length(Long.parseLong(length));
+
+            if (getConfiguration().getServerSideEncryptionCustomerKey() != 
null) {
+                
getObjectRequest.ssec(getConfiguration().getServerSideEncryptionCustomerKey());
+            }
+
+            InputStream respond = 
minioClient.getObject(getObjectRequest.build());
 
             Message message = getMessageForResponse(exchange);
             message.setBody(respond);
diff --git 
a/components/camel-minio/src/test/java/org/apache/camel/component/minio/MinioProducerEncryptionTest.java
 
b/components/camel-minio/src/test/java/org/apache/camel/component/minio/MinioProducerEncryptionTest.java
new file mode 100644
index 000000000000..98ad4c0ac899
--- /dev/null
+++ 
b/components/camel-minio/src/test/java/org/apache/camel/component/minio/MinioProducerEncryptionTest.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.minio;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import io.minio.BucketExistsArgs;
+import io.minio.CopyObjectArgs;
+import io.minio.GetObjectArgs;
+import io.minio.GetObjectResponse;
+import io.minio.MinioClient;
+import io.minio.ObjectWriteResponse;
+import io.minio.PutObjectArgs;
+import io.minio.ServerSideEncryption;
+import org.apache.camel.Exchange;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class MinioProducerEncryptionTest extends CamelTestSupport {
+
+    private MinioClient minioClient;
+    private SecretKey secretKey;
+
+    @BeforeEach
+    void init() throws Exception {
+        minioClient = mock(MinioClient.class);
+        
when(minioClient.bucketExists(any(BucketExistsArgs.class))).thenReturn(true);
+        KeyGenerator generator = KeyGenerator.getInstance("AES");
+        generator.init(256);
+        secretKey = generator.generateKey();
+    }
+
+    private MinioProducer createProducer(MinioEndpoint endpoint) throws 
Exception {
+        endpoint.start();
+        MinioProducer producer = new MinioProducer(endpoint);
+        producer.start();
+        return producer;
+    }
+
+    @Test
+    void putObjectWithServerSideEncryption() throws Exception {
+        ServerSideEncryption.S3 sse = new ServerSideEncryption.S3();
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryption(sse);
+
+        
when(minioClient.putObject(any(PutObjectArgs.class))).thenReturn(mock(ObjectWriteResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "test.txt");
+        exchange.getIn().setBody("content");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<PutObjectArgs> captor = 
ArgumentCaptor.forClass(PutObjectArgs.class);
+        verify(minioClient).putObject(captor.capture());
+        assertSame(sse, captor.getValue().sse());
+        producer.stop();
+        endpoint.stop();
+    }
+
+    @Test
+    void putObjectWithCustomerKey() throws Exception {
+        ServerSideEncryption.CustomerKey ssec = new 
ServerSideEncryption.CustomerKey(secretKey);
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryptionCustomerKey(ssec);
+
+        
when(minioClient.putObject(any(PutObjectArgs.class))).thenReturn(mock(ObjectWriteResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "test.txt");
+        exchange.getIn().setBody("content");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<PutObjectArgs> captor = 
ArgumentCaptor.forClass(PutObjectArgs.class);
+        verify(minioClient).putObject(captor.capture());
+        assertSame(ssec, captor.getValue().sse());
+        producer.stop();
+        endpoint.stop();
+    }
+
+    @Test
+    void producerStartWithBothEncryptionOptionsThrows() throws Exception {
+        ServerSideEncryption.S3 sse = new ServerSideEncryption.S3();
+        ServerSideEncryption.CustomerKey ssec = new 
ServerSideEncryption.CustomerKey(secretKey);
+
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryption(sse);
+        endpoint.getConfiguration().setServerSideEncryptionCustomerKey(ssec);
+
+        endpoint.start();
+        MinioProducer producer = new MinioProducer(endpoint);
+        assertThrows(IllegalArgumentException.class, producer::start);
+        endpoint.stop();
+    }
+
+    @Test
+    void copyObjectWithServerSideEncryption() throws Exception {
+        ServerSideEncryption.S3 sse = new ServerSideEncryption.S3();
+
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryption(sse);
+
+        
when(minioClient.copyObject(any(CopyObjectArgs.class))).thenReturn(mock(ObjectWriteResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.MINIO_OPERATION, 
MinioOperations.copyObject);
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "source.txt");
+        exchange.getIn().setHeader(MinioConstants.DESTINATION_OBJECT_NAME, 
"dest.txt");
+        exchange.getIn().setHeader(MinioConstants.DESTINATION_BUCKET_NAME, 
"dest-bucket");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<CopyObjectArgs> captor = 
ArgumentCaptor.forClass(CopyObjectArgs.class);
+        verify(minioClient).copyObject(captor.capture());
+        assertSame(sse, captor.getValue().sse());
+        producer.stop();
+        endpoint.stop();
+    }
+
+    @Test
+    void copyObjectWithCustomerKey() throws Exception {
+        ServerSideEncryption.CustomerKey ssec = new 
ServerSideEncryption.CustomerKey(secretKey);
+
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryptionCustomerKey(ssec);
+
+        
when(minioClient.copyObject(any(CopyObjectArgs.class))).thenReturn(mock(ObjectWriteResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.MINIO_OPERATION, 
MinioOperations.copyObject);
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "source.txt");
+        exchange.getIn().setHeader(MinioConstants.DESTINATION_OBJECT_NAME, 
"dest.txt");
+        exchange.getIn().setHeader(MinioConstants.DESTINATION_BUCKET_NAME, 
"dest-bucket");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<CopyObjectArgs> captor = 
ArgumentCaptor.forClass(CopyObjectArgs.class);
+        verify(minioClient).copyObject(captor.capture());
+        assertSame(ssec, captor.getValue().sse());
+        assertNotNull(captor.getValue().source());
+        assertSame(ssec, captor.getValue().source().ssec());
+        producer.stop();
+        endpoint.stop();
+    }
+
+    @Test
+    void getObjectWithCustomerKey() throws Exception {
+        ServerSideEncryption.CustomerKey ssec = new 
ServerSideEncryption.CustomerKey(secretKey);
+
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryptionCustomerKey(ssec);
+
+        
when(minioClient.getObject(any(GetObjectArgs.class))).thenReturn(mock(GetObjectResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.MINIO_OPERATION, 
MinioOperations.getObject);
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "test.txt");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<GetObjectArgs> captor = 
ArgumentCaptor.forClass(GetObjectArgs.class);
+        verify(minioClient).getObject(captor.capture());
+        assertSame(ssec, captor.getValue().ssec());
+        producer.stop();
+        endpoint.stop();
+    }
+
+    @Test
+    void getPartialObjectWithCustomerKey() throws Exception {
+        ServerSideEncryption.CustomerKey ssec = new 
ServerSideEncryption.CustomerKey(secretKey);
+
+        MinioComponent component = context.getComponent("minio", 
MinioComponent.class);
+        MinioEndpoint endpoint = (MinioEndpoint) 
component.createEndpoint("minio://mybucket?autoCreateBucket=false");
+        endpoint.getConfiguration().setMinioClient(minioClient);
+        endpoint.getConfiguration().setServerSideEncryptionCustomerKey(ssec);
+
+        
when(minioClient.getObject(any(GetObjectArgs.class))).thenReturn(mock(GetObjectResponse.class));
+
+        MinioProducer producer = createProducer(endpoint);
+        Exchange exchange = endpoint.createExchange();
+        exchange.getIn().setHeader(MinioConstants.MINIO_OPERATION, 
MinioOperations.getPartialObject);
+        exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "test.txt");
+        exchange.getIn().setHeader(MinioConstants.OFFSET, "10");
+        exchange.getIn().setHeader(MinioConstants.LENGTH, "20");
+
+        producer.process(exchange);
+
+        ArgumentCaptor<GetObjectArgs> captor = 
ArgumentCaptor.forClass(GetObjectArgs.class);
+        verify(minioClient).getObject(captor.capture());
+        assertSame(ssec, captor.getValue().ssec());
+        assertEquals(10L, captor.getValue().offset());
+        assertEquals(20L, captor.getValue().length());
+        producer.stop();
+        endpoint.stop();
+    }
+}

Reply via email to