-
Notifications
You must be signed in to change notification settings - Fork 18
SSE_C changes #281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SSE_C changes #281
Changes from all commits
d7d3609
70bd9d4
809475a
2147905
314ede6
af9204c
d7e58ca
856d741
751e97b
1080fd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /* | ||
| * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Licensed 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 software.amazon.s3.analyticsaccelerator.request; | ||
|
|
||
| import java.security.MessageDigest; | ||
| import java.security.NoSuchAlgorithmException; | ||
| import java.util.Base64; | ||
| import java.util.Optional; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| /** | ||
| * Contains encryption secrets for Server-Side Encryption with Customer-Provided Keys (SSE-C). This | ||
| * class manages the customer-provided encryption key used for SSE-C operations with Amazon S3. | ||
| */ | ||
| @Getter | ||
| public class EncryptionSecrets { | ||
|
|
||
| /** | ||
| * The customer-provided encryption key for SSE-C operations. When present, this key will be used | ||
| * for server-side encryption. The key must be Base64 encoded and exactly 256 bits (32 bytes) when | ||
| * decoded. | ||
| */ | ||
| private final Optional<String> ssecCustomerKey; | ||
|
|
||
| /** | ||
| * The Base64-encoded MD5 hash of the customer key. This hash is automatically calculated from the | ||
| * customer key and is used by Amazon S3 to verify the integrity of the encryption key during | ||
| * transmission. Will be null if no customer key is provided. | ||
| */ | ||
| private final String ssecCustomerKeyMd5; | ||
|
|
||
| /** | ||
| * Constructs an EncryptionSecrets instance with the specified SSE-C customer key. | ||
| * | ||
| * <p>This constructor processes the SSE-C (Server-Side Encryption with Customer-Provided Keys) | ||
| * encryption key and calculates its MD5 hash as required by Amazon S3. The process involves: | ||
| * | ||
| * <ol> | ||
| * <li>Accepting a Base64-encoded encryption key | ||
| * <li>Decoding the Base64 key back to bytes | ||
| * <li>Computing the MD5 hash of these bytes | ||
| * <li>Encoding the MD5 hash in Base64 format | ||
| * </ol> | ||
| * | ||
| * @param sseCustomerKey An Optional containing the Base64-encoded encryption key, or empty if no | ||
| * encryption is needed | ||
| */ | ||
| @Builder | ||
| public EncryptionSecrets(Optional<String> sseCustomerKey) { | ||
| this.ssecCustomerKey = sseCustomerKey; | ||
| this.ssecCustomerKeyMd5 = | ||
| sseCustomerKey | ||
| .map( | ||
| key -> { | ||
| try { | ||
| MessageDigest md = MessageDigest.getInstance("MD5"); | ||
| return Base64.getEncoder() | ||
rajdchak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .encodeToString(md.digest(Base64.getDecoder().decode(key))); | ||
| } catch (NoSuchAlgorithmException e) { | ||
| throw new IllegalStateException("MD5 algorithm not available", e); | ||
| } | ||
| }) | ||
| .orElse(null); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,7 @@ | |
| import software.amazon.awssdk.services.s3.model.S3Exception; | ||
| import software.amazon.s3.analyticsaccelerator.S3SeekableInputStream; | ||
| import software.amazon.s3.analyticsaccelerator.common.ObjectRange; | ||
| import software.amazon.s3.analyticsaccelerator.util.OpenStreamInformation; | ||
| import software.amazon.s3.analyticsaccelerator.util.S3URI; | ||
|
|
||
| /** Base class for the integration tests */ | ||
|
|
@@ -99,7 +100,11 @@ protected void testAndCompareStreamReadPattern( | |
| // Read using the standard S3 async client | ||
| Crc32CChecksum directChecksum = new Crc32CChecksum(); | ||
| executeReadPatternDirectly( | ||
| s3ClientKind, s3Object, streamReadPattern, Optional.of(directChecksum)); | ||
| s3ClientKind, | ||
| s3Object, | ||
| streamReadPattern, | ||
| Optional.of(directChecksum), | ||
| OpenStreamInformation.DEFAULT); | ||
|
|
||
| // Read using the AAL S3 | ||
| Crc32CChecksum aalChecksum = new Crc32CChecksum(); | ||
|
|
@@ -108,7 +113,8 @@ protected void testAndCompareStreamReadPattern( | |
| s3Object, | ||
| streamReadPattern, | ||
| AALInputStreamConfigurationKind, | ||
| Optional.of(aalChecksum)); | ||
| Optional.of(aalChecksum), | ||
| OpenStreamInformation.DEFAULT); | ||
|
|
||
| // Assert checksums | ||
| assertChecksums(directChecksum, aalChecksum); | ||
|
|
@@ -140,7 +146,8 @@ protected void testChangingEtagMidStream( | |
| S3URI s3URI = | ||
| s3Object.getObjectUri(this.getS3ExecutionContext().getConfiguration().getBaseUri()); | ||
| S3AsyncClient s3Client = this.getS3ExecutionContext().getS3Client(); | ||
| S3SeekableInputStream stream = s3AALClientStreamReader.createReadStream(s3Object); | ||
| S3SeekableInputStream stream = | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you could've saved yourself lots of time keeping createReadStream(s3Object) method around and inside call createReadStream(s3Object, OpenStreamInformation.DEFAULT).
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nit btw but probably a better way to implement this pattern. |
||
|
|
||
| // Read first 100 bytes | ||
| readAndAssert(stream, buffer, 0, 100); | ||
|
|
@@ -171,7 +178,11 @@ protected void testChangingEtagMidStream( | |
| assertDoesNotThrow( | ||
| () -> | ||
| executeReadPatternOnAAL( | ||
| s3Object, s3AALClientStreamReader, streamReadPattern, Optional.of(datChecksum))); | ||
| s3Object, | ||
| s3AALClientStreamReader, | ||
| streamReadPattern, | ||
| Optional.of(datChecksum), | ||
| OpenStreamInformation.DEFAULT)); | ||
| assert (datChecksum.getChecksumBytes().length > 0); | ||
| } | ||
| } | ||
|
|
@@ -199,7 +210,7 @@ protected void testReadVectored( | |
| this.createS3AALClientStreamReader(s3ClientKind, AALInputStreamConfigurationKind)) { | ||
|
|
||
| S3SeekableInputStream s3SeekableInputStream = | ||
| s3AALClientStreamReader.createReadStream(s3Object); | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
|
|
||
| List<ObjectRange> objectRanges = new ArrayList<>(); | ||
| objectRanges.add(new ObjectRange(new CompletableFuture<>(), 50, 500)); | ||
|
|
@@ -217,7 +228,7 @@ protected void testReadVectored( | |
| ByteBuffer byteBuffer = objectRange.getByteBuffer().join(); | ||
|
|
||
| S3SeekableInputStream verificationStream = | ||
| s3AALClientStreamReader.createReadStream(s3Object); | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
| verificationStream.seek(objectRange.getOffset()); | ||
| byte[] buffer = new byte[objectRange.getLength()]; | ||
| int readBytes = verificationStream.read(buffer, 0, buffer.length); | ||
|
|
@@ -273,7 +284,8 @@ protected void testChangingEtagAfterStreamPassesAndReturnsCachedObject( | |
| // Create the s3DATClientStreamReader - that creates the shared state | ||
| try (S3AALClientStreamReader s3AALClientStreamReader = | ||
| this.createS3AALClientStreamReader(s3ClientKind, AALInputStreamConfigurationKind)) { | ||
| S3SeekableInputStream stream = s3AALClientStreamReader.createReadStream(s3Object); | ||
| S3SeekableInputStream stream = | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
| Crc32CChecksum datChecksum = calculateCRC32C(stream, bufferSize); | ||
|
|
||
| S3URI s3URI = | ||
|
|
@@ -287,7 +299,8 @@ protected void testChangingEtagAfterStreamPassesAndReturnsCachedObject( | |
| AsyncRequestBody.fromBytes(generateRandomBytes(bufferSize))) | ||
| .join(); | ||
|
|
||
| S3SeekableInputStream cacheStream = s3AALClientStreamReader.createReadStream(s3Object); | ||
| S3SeekableInputStream cacheStream = | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
| Crc32CChecksum cachedChecksum = calculateCRC32C(cacheStream, bufferSize); | ||
|
|
||
| // Assert checksums | ||
|
|
@@ -351,7 +364,11 @@ protected void testAALReadConcurrency( | |
| // Read using the standard S3 async client. We do this once, to calculate the checksums | ||
| Crc32CChecksum directChecksum = new Crc32CChecksum(); | ||
| executeReadPatternDirectly( | ||
| s3ClientKind, s3Object, streamReadPattern, Optional.of(directChecksum)); | ||
| s3ClientKind, | ||
| s3Object, | ||
| streamReadPattern, | ||
| Optional.of(directChecksum), | ||
| OpenStreamInformation.DEFAULT); | ||
|
|
||
| // Create the s3DATClientStreamReader - that creates the shared state | ||
| try (S3AALClientStreamReader s3AALClientStreamReader = | ||
|
|
@@ -374,7 +391,8 @@ protected void testAALReadConcurrency( | |
| s3Object, | ||
| s3AALClientStreamReader, | ||
| streamReadPattern, | ||
| Optional.of(datChecksum)); | ||
| Optional.of(datChecksum), | ||
| OpenStreamInformation.DEFAULT); | ||
|
|
||
| // Assert checksums | ||
| assertChecksums(directChecksum, datChecksum); | ||
|
|
@@ -418,7 +436,8 @@ protected void testSmallObjectPrefetching( | |
| this.createS3AALClientStreamReader(s3ClientKind, AALInputStreamConfigurationKind)) { | ||
|
|
||
| // First stream | ||
| S3SeekableInputStream stream = s3AALClientStreamReader.createReadStream(s3Object); | ||
| S3SeekableInputStream stream = | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
| Crc32CChecksum firstChecksum = calculateCRC32C(stream, (int) s3Object.getSize()); | ||
|
|
||
| S3URI s3URI = | ||
|
|
@@ -433,7 +452,8 @@ protected void testSmallObjectPrefetching( | |
| .join(); | ||
|
|
||
| // Create second stream | ||
| S3SeekableInputStream secondStream = s3AALClientStreamReader.createReadStream(s3Object); | ||
| S3SeekableInputStream secondStream = | ||
| s3AALClientStreamReader.createReadStream(s3Object, OpenStreamInformation.DEFAULT); | ||
| Crc32CChecksum secondChecksum = calculateCRC32C(secondStream, (int) s3Object.getSize()); | ||
|
|
||
| if (s3Object.getSize() < 8 * ONE_MB) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.