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
