Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
package software.amazon.encryption.s3.internal;

import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;

@FunctionalInterface
public interface ContentMetadataDecodingStrategy {
ContentMetadata decodeMetadata(GetObjectRequest request, GetObjectResponse response);
ContentMetadata decodeMetadata(GetObjectRequest request, GetObjectResponse response, S3AsyncClient s3AsyncClient);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
package software.amazon.encryption.s3.internal;

import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser;
import software.amazon.awssdk.protocols.jsoncore.JsonWriter;
import software.amazon.awssdk.protocols.jsoncore.JsonWriter.JsonGenerationException;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
Expand All @@ -17,6 +18,7 @@
import software.amazon.encryption.s3.materials.EncryptionMaterials;
import software.amazon.encryption.s3.materials.S3Keyring;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
Expand All @@ -33,30 +35,28 @@ public abstract class ContentMetadataStrategy implements ContentMetadataEncoding
public static final ContentMetadataDecodingStrategy INSTRUCTION_FILE = new ContentMetadataDecodingStrategy() {

@Override
public ContentMetadata decodeMetadata(GetObjectRequest getObjectRequest, GetObjectResponse response) {
public ContentMetadata decodeMetadata(GetObjectRequest getObjectRequest, GetObjectResponse response, S3AsyncClient s3AsyncClient) {
GetObjectRequest instructionGetObjectRequest = GetObjectRequest.builder()
.bucket(getObjectRequest.bucket())
.key(getObjectRequest.key() + INSTRUCTION_FILE_SUFFIX)
.build();

S3Client s3Client = S3Client.create();
ResponseInputStream<GetObjectResponse> instruction;
try {
instruction = s3Client.getObject(instructionGetObjectRequest);
try (ResponseInputStream<GetObjectResponse> instruction = s3AsyncClient.getObject(instructionGetObjectRequest, AsyncResponseTransformer.toBlockingInputStream()).join()){
Map<String, String> metadata = new HashMap<>();
JsonNodeParser parser = JsonNodeParser.create();
JsonNode objectNode = parser.parse(instruction);
for (Map.Entry<String, JsonNode> entry : objectNode.asObject().entrySet()) {
metadata.put(entry.getKey(), entry.getValue().asString());
}
return ContentMetadataStrategy.readFromMap(metadata, response);
} catch (IOException ioException) {
throw new S3EncryptionClientException("IOException while reading instruction file!", ioException);
} catch (NoSuchKeyException exception) {
// Most likely, the customer is attempting to decrypt an object
// which is not encrypted with the S3 EC.
throw new S3EncryptionClientException("Instruction file not found! Please ensure the object you are" +
" attempting to decrypt has been encrypted using the S3 Encryption Client.", exception);
}

Map<String, String> metadata = new HashMap<>();
JsonNodeParser parser = JsonNodeParser.create();
JsonNode objectNode = parser.parse(instruction);
for (Map.Entry<String, JsonNode> entry : objectNode.asObject().entrySet()) {
metadata.put(entry.getKey(), entry.getValue().asString());
" attempting to decrypt has been encrypted using the S3 Encryption Client.", exception);
}
return ContentMetadataStrategy.readFromMap(metadata, response);
}
};

Expand Down Expand Up @@ -88,7 +88,7 @@ public Map<String, String> encodeMetadata(EncryptionMaterials materials, byte[]
}

@Override
public ContentMetadata decodeMetadata(GetObjectRequest request, GetObjectResponse response) {
public ContentMetadata decodeMetadata(GetObjectRequest request, GetObjectResponse response, S3AsyncClient s3AsyncClient) {
return ContentMetadataStrategy.readFromMap(response.metadata(), response);
}
};
Expand Down Expand Up @@ -211,7 +211,7 @@ private static ContentMetadata readFromMap(Map<String, String> metadata, GetObje
.build();
}

public static ContentMetadata decode(GetObjectRequest request, GetObjectResponse response) {
public static ContentMetadata decode(GetObjectRequest request, GetObjectResponse response, S3AsyncClient s3AsyncClient) {
Map<String, String> metadata = response.metadata();
ContentMetadataDecodingStrategy strategy;
if (metadata != null
Expand All @@ -223,6 +223,6 @@ public static ContentMetadata decode(GetObjectRequest request, GetObjectResponse
strategy = INSTRUCTION_FILE;
}

return strategy.decodeMetadata(request, response);
return strategy.decodeMetadata(request, response, s3AsyncClient);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public CompletableFuture<T> prepare() {
@Override
public void onResponse(GetObjectResponse response) {
getObjectResponse = response;
contentMetadata = ContentMetadataStrategy.decode(getObjectRequest, response);
contentMetadata = ContentMetadataStrategy.decode(getObjectRequest, response, _s3AsyncClient);
materials = prepareMaterialsFromRequest(getObjectRequest, response, contentMetadata);
wrappedAsyncResponseTransformer.onResponse(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void decodeWithObjectMetadata() {
.contentIv(bytes)
.build();

ContentMetadata contentMetadata = ContentMetadataStrategy.decode(getObjectRequest, getObjectResponse);
ContentMetadata contentMetadata = ContentMetadataStrategy.decode(getObjectRequest, getObjectResponse, null);
assertEquals(expectedContentMetadata.algorithmSuite(), contentMetadata.algorithmSuite());
String actualContentIv = Arrays.toString(contentMetadata.contentIv());
String expectedContentIv = Arrays.toString(expectedContentMetadata.contentIv());
Expand Down