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

daim pushed a commit to branch OAK-10093
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 9e3fe63d517dbcc32a06ee578ebc3b260a1ae8e5
Author: Rishabh Kumar <[email protected]>
AuthorDate: Thu Jun 1 15:01:39 2023 +0530

    OAK-10093 : provided support for SSE Customer Keys for AWS
---
 .../jackrabbit/oak/blob/cloud/s3/S3Constants.java  | 10 ++++
 .../oak/blob/cloud/s3/S3RequestDecorator.java      | 43 +++++++++++++++--
 .../blob/cloud/s3/TestS3DSWithSSECustomerKey.java  | 54 ++++++++++++++++++++++
 oak-blob-cloud/src/test/resources/aws.properties   |  1 +
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git 
a/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
 
b/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
index e8ed6f00b0..62877b9c9b 100644
--- 
a/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
+++ 
b/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
@@ -107,11 +107,21 @@ public final class S3Constants {
      */
     public static final String S3_ENCRYPTION_SSE_KMS = "SSE_KMS";
 
+    /**
+     *  Constant to set SSE_KMS encryption.
+     */
+    public static final String S3_ENCRYPTION_SSE_C = "SSE_C";
+
     /**
      *  Constant to set keyID for SSE_KMS encryption.
      */
     public static final String S3_SSE_KMS_KEYID = "kmsKeyId";
 
+    /**
+     *  Constant to set keyID for SSE_C encryption.
+     */
+    public static final String S3_SSE_C_KEYID = "sseCustomerKeyId";
+
     /**
      *  Constant to set S3 signature for SSE_KMS encryption.
      */
diff --git 
a/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3RequestDecorator.java
 
b/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3RequestDecorator.java
index 3d136795c5..af670c436b 100644
--- 
a/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3RequestDecorator.java
+++ 
b/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3RequestDecorator.java
@@ -26,7 +26,15 @@ import com.amazonaws.services.s3.model.ObjectMetadata;
 import com.amazonaws.services.s3.model.PutObjectRequest;
 import com.amazonaws.services.s3.model.SSEAlgorithm;
 import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams;
-import com.amazonaws.util.StringUtils;
+import com.amazonaws.services.s3.model.SSECustomerKey;
+
+import java.util.Objects;
+
+import static com.amazonaws.services.s3.model.SSEAlgorithm.AES256;
+import static com.amazonaws.util.StringUtils.hasValue;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3Constants.S3_ENCRYPTION_SSE_C;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3Constants.S3_SSE_C_KEYID;
 
 /**
  * This class to sets encrption mode in S3 request.
@@ -37,17 +45,24 @@ public class S3RequestDecorator {
     Properties props;
     SSEAwsKeyManagementParams sseParams;
 
+    SSECustomerKey sseCustomerKey;
+
     public S3RequestDecorator(Properties props) {
         String encryptionType = props.getProperty(S3Constants.S3_ENCRYPTION);
         if (encryptionType != null) {
-            this.dataEncryption = dataEncryption.valueOf(encryptionType);
+            this.dataEncryption = DataEncryption.valueOf(encryptionType);
 
             if (encryptionType.equals(S3Constants.S3_ENCRYPTION_SSE_KMS)) {
                 String keyId = props.getProperty(S3Constants.S3_SSE_KMS_KEYID);
                 sseParams = new SSEAwsKeyManagementParams();
-                if (!StringUtils.isNullOrEmpty(keyId)) {
+                if (hasValue(keyId)) {
                     sseParams.withAwsKmsKeyId(keyId);
                 }
+            } else if (Objects.equals(S3_ENCRYPTION_SSE_C, encryptionType)) {
+                final String keyId = props.getProperty(S3_SSE_C_KEYID);
+                if (hasValue(keyId)) {
+                    sseCustomerKey = new SSECustomerKey(keyId.getBytes(UTF_8));
+                }
             }
         }
     }
@@ -68,6 +83,10 @@ public class S3RequestDecorator {
                 /*Set*/
                 request.withSSEAwsKeyManagementParams(sseParams);
                 break;
+            case SSE_C:
+                metadata.setSSEAlgorithm(AES256.getAlgorithm());
+                request.withSSECustomerKey(sseCustomerKey);
+                break;
             case NONE:
                 break;
         }
@@ -90,6 +109,10 @@ public class S3RequestDecorator {
                 metadata.setSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
                 request.withSSEAwsKeyManagementParams(sseParams);
                 break;
+            case SSE_C:
+                metadata.setSSEAlgorithm(AES256.getAlgorithm());
+                
request.withSourceSSECustomerKey(sseCustomerKey).withDestinationSSECustomerKey(sseCustomerKey);
+                break;
             case NONE:
                 break;
         }
@@ -109,6 +132,10 @@ public class S3RequestDecorator {
                 metadata.setSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
                 request.withSSEAwsKeyManagementParams(sseParams);
                 break;
+            case SSE_C:
+                metadata.setSSEAlgorithm(AES256.getAlgorithm());
+                request.withSSECustomerKey(sseCustomerKey);
+                break;
             case NONE:
                 break;
         }
@@ -124,6 +151,10 @@ public class S3RequestDecorator {
               if (keyId != null) {
                   request = request.withKmsCmkId(keyId);
               }
+              break;
+          case SSE_C:
+              request = 
request.withSSEAlgorithm(AES256).withSSECustomerKey(getSseCustomerKey());
+              break;
         }
         return request;
     }
@@ -132,6 +163,10 @@ public class S3RequestDecorator {
         return this.sseParams;
     }
 
+    private SSECustomerKey getSseCustomerKey() {
+        return this.sseCustomerKey;
+    }
+
     private DataEncryption getDataEncryption() {
         return this.dataEncryption;
     }
@@ -141,7 +176,7 @@ public class S3RequestDecorator {
      *
      */
     private enum DataEncryption {
-        SSE_S3, SSE_KMS, NONE;
+        SSE_S3, SSE_KMS, SSE_C, NONE;
     }
 
 }
diff --git 
a/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DSWithSSECustomerKey.java
 
b/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DSWithSSECustomerKey.java
new file mode 100644
index 0000000000..f49ef0e01b
--- /dev/null
+++ 
b/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DSWithSSECustomerKey.java
@@ -0,0 +1,54 @@
+/*
+ * 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.jackrabbit.oak.blob.cloud.s3;
+
+import org.junit.AssumptionViolatedException;
+import org.junit.Before;
+import org.slf4j.Logger;
+
+import static com.amazonaws.util.StringUtils.hasValue;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3Constants.S3_ENCRYPTION;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3Constants.S3_ENCRYPTION_SSE_C;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3Constants.S3_SSE_C_KEYID;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Test S3DataStore operation with SSE_C encryption.
+ * It requires to pass aws config file via system property  or system 
properties by prefixing with 'ds.'.
+ * See details @ {@link S3DataStoreUtils}.
+ * For e.g. -Dconfig=/opt/cq/aws.properties. Sample aws properties located at
+ * src/test/resources/aws.properties
+ *
+ */
+public class TestS3DSWithSSECustomerKey extends TestS3Ds {
+
+        protected static final Logger LOG = 
getLogger(TestS3DSWithSSECustomerKey.class);
+
+        @Override
+        @Before
+        public void setUp() throws Exception {
+            super.setUp();
+            String keyId = props.getProperty(S3_SSE_C_KEYID);
+            if (hasValue(keyId)) {
+                props.setProperty(S3_ENCRYPTION, S3_ENCRYPTION_SSE_C);
+                props.setProperty(S3_SSE_C_KEYID, keyId);
+            } else {
+                LOG.info("SSE Customer Key ID not configured so ignoring 
test");
+                throw new AssumptionViolatedException("SSE Customer key Id not 
configured");
+            }
+        }
+}
diff --git a/oak-blob-cloud/src/test/resources/aws.properties 
b/oak-blob-cloud/src/test/resources/aws.properties
index e23ed0c3fd..6eaaa3a4bc 100644
--- a/oak-blob-cloud/src/test/resources/aws.properties
+++ b/oak-blob-cloud/src/test/resources/aws.properties
@@ -35,6 +35,7 @@ s3Region=
 # and has a higher precedence over endpoint derived
 # via S3 region.
 kmsKeyId=
+sseCustomerKeyId=
 connectionTimeout=120000
 socketTimeout=120000
 maxConnections=20

Reply via email to