diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java index 093ba2ab..f8eb52fa 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java @@ -5,46 +5,30 @@ package software.amazon.encryption.s3; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static software.amazon.encryption.s3.TestUtils.*; +import static software.amazon.encryption.s3.TestUtils.appendTestSuffix; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import com.amazonaws.services.s3.model.KMSEncryptionMaterials; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.api.Nested; -import software.amazon.encryption.s3.client.S3ECTestServerClient; -import software.amazon.encryption.s3.model.CommitmentPolicy; -import software.amazon.encryption.s3.model.CreateClientInput; -import software.amazon.encryption.s3.model.CreateClientOutput; -import software.amazon.encryption.s3.model.GetObjectInput; -import software.amazon.encryption.s3.model.GetObjectOutput; -import software.amazon.encryption.s3.model.KeyMaterial; -import software.amazon.encryption.s3.model.PutObjectInput; -import software.amazon.encryption.s3.model.S3ECConfig; -import software.amazon.encryption.s3.model.S3EncryptionClientError; -import software.amazon.encryption.s3.model.EncryptionAlgorithm; import com.amazonaws.services.s3.AmazonS3Encryption; import com.amazonaws.services.s3.AmazonS3EncryptionClient; import com.amazonaws.services.s3.model.CryptoConfiguration; import com.amazonaws.services.s3.model.CryptoMode; import com.amazonaws.services.s3.model.CryptoStorageMode; -import software.amazon.encryption.s3.TestUtils.*; import com.amazonaws.services.s3.model.EncryptionMaterialsProvider; import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider; +import software.amazon.encryption.s3.client.S3ECTestServerClient; +import software.amazon.encryption.s3.model.CommitmentPolicy; +import software.amazon.encryption.s3.model.CreateClientInput; +import software.amazon.encryption.s3.model.CreateClientOutput; +import software.amazon.encryption.s3.model.EncryptionAlgorithm; +import software.amazon.encryption.s3.model.KeyMaterial; +import software.amazon.encryption.s3.model.S3ECConfig; + /** * Exhaustive tests for S3 Encryption Client round-trip operations. * These tests cover various combinations of client versions, commitment policies, and encryption modes. @@ -181,4 +165,75 @@ void improved_configured_with_the_default_should_fail_to_decrypt_cbc(TestUtils.L TestUtils.Decrypt_fails(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } + + // Ranged Get Tests - using existing CBC encrypted object with ranged-get-supported clients + + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should FAIL to ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet_fails(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java index 6eef0b5f..03e16095 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java @@ -5,48 +5,24 @@ package software.amazon.encryption.s3; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static software.amazon.encryption.s3.TestUtils.*; +import static software.amazon.encryption.s3.TestUtils.appendTestSuffix; -import java.lang.annotation.ElementType; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import com.amazonaws.services.s3.model.KMSEncryptionMaterials; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import software.amazon.encryption.s3.client.S3ECTestServerClient; import software.amazon.encryption.s3.model.CommitmentPolicy; import software.amazon.encryption.s3.model.CreateClientInput; import software.amazon.encryption.s3.model.CreateClientOutput; import software.amazon.encryption.s3.model.EncryptionAlgorithm; -import software.amazon.encryption.s3.model.GetObjectInput; -import software.amazon.encryption.s3.model.GetObjectOutput; import software.amazon.encryption.s3.model.KeyMaterial; -import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.S3ECConfig; -import software.amazon.encryption.s3.model.S3EncryptionClientError; - -import com.amazonaws.services.s3.AmazonS3Encryption; -import com.amazonaws.services.s3.AmazonS3EncryptionClient; -import com.amazonaws.services.s3.model.CryptoConfiguration; -import com.amazonaws.services.s3.model.CryptoMode; -import com.amazonaws.services.s3.model.CryptoStorageMode; -import software.amazon.encryption.s3.TestUtils.*; -import com.amazonaws.services.s3.model.EncryptionMaterialsProvider; -import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider; /** * Exhaustive tests for S3 Encryption Client round-trip operations. @@ -159,6 +135,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_gcm( .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); @@ -199,5 +176,94 @@ void improved_configured_with_require_encrypt_require_decrypt_should_fail_to_dec TestUtils.Decrypt_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); } + + // Ranged Get Tests - using existing GCM encrypted objects with ranged-get-supported clients + + @Order(21) + @ParameterizedTest(name = "{0}: Transition configured with the default can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_the_default_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(22) + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(23) + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(24) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(25) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should fail to ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_fail_to_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java index ee4279d6..acdbf045 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java @@ -1,7 +1,7 @@ /* -* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -* SPDX-License-Identifier: Apache-2.0 -*/ + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ package software.amazon.encryption.s3; @@ -30,23 +30,23 @@ import software.amazon.encryption.s3.model.S3ECConfig; /** -* Exhaustive tests for S3 Encryption Client round-trip operations. -* These tests cover various combinations of client versions, commitment policies, and encryption modes. -* -* Tests are based on the exhaustive test matrix defined at: -* https://tiny.amazon.com/3xnzwczl/loopcloumicrpeyJ3 -* -*/ + * Exhaustive tests for S3 Encryption Client round-trip operations. + * These tests cover various combinations of client versions, commitment policies, and encryption modes. + * + * Tests are based on the exhaustive test matrix defined at: + * https://tiny.amazon.com/3xnzwczl/loopcloumicrpeyJ3 + * + */ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class KC_GCMTests { private static final String sharedObjectKeyBaseMetaDataMode = "test-kc-gcm-kms"; private static final String sharedObjectKeyBaseInsFileMode = "test-kc-gcm-kms-instruction-file"; private static KeyMaterial kmsKeyArn = KeyMaterial.builder() - .kmsKeyId(TestUtils.KMS_KEY_ARN) - .build(); + .kmsKeyId(TestUtils.KMS_KEY_ARN) + .build(); private static final List crossLanguageObjectsMetaDataMode = new ArrayList<>(); - private static final List crossLanguageObjectsInstructionFiles = new ArrayList<>(); + private static final List crossLanguageObjectsRawRsaInstructionFiles = new ArrayList<>(); private static KeyPair RSA_KEY_PAIR_1; @BeforeAll @@ -55,7 +55,7 @@ static void setupKeys() throws Exception { keyPairGen.initialize(2048); RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); } - + @Order(1) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") @@ -68,12 +68,12 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) - @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt with InstructionFilePutObject should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { if (!RAW_SUPPORTED.contains(language.getLanguageName())) { @@ -95,8 +95,8 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .keyMaterial(rsaKey).build()) .build()); String S3ECId = clientOutput.getClientId(); - - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsRawRsaInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -111,7 +111,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @@ -127,15 +127,15 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } - + @Order(10) @ParameterizedTest(name = "{0}: Transition configured with the default should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#transitionClientsForTest") void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -144,7 +144,7 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @@ -152,7 +152,7 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#transitionClientsForTest") void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -161,7 +161,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @@ -169,7 +169,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -179,15 +179,15 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } - + @Order(13) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -196,15 +196,15 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gc .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } - + @Order(14) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -213,7 +213,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @@ -230,12 +230,12 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua .build()) .build()); String S3ECId = clientOutput.getClientId(); - + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } - + @Order(16) - @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt decrypt InstructionFilePutObject KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm_ins_file(final TestUtils.LanguageServerTarget language) { if (!RAW_SUPPORTED.contains(language.getLanguageName())) { @@ -257,8 +257,114 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .keyMaterial(rsaKey).build()) .build()); String S3ECId = clientOutput.getClientId(); - - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsRawRsaInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } - + + // Ranged Get Tests - using existing KC-GCM encrypted objects with ranged-get-supported clients + + @Order(20) + @ParameterizedTest(name = "{0}: Transition configured with the default can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(21) + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(22) + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(23) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(24) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(25) + @ParameterizedTest(name = "{0}: Improved configured with the default can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index d3d25d58..095aa044 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -6,17 +6,20 @@ package software.amazon.encryption.s3; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.net.Socket; import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Random; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -116,6 +119,29 @@ public class TestUtils { public static final Set INSTRUCTION_FILE_GET_UNSUPPORTED = Set.of(PYTHON_V3); + // PHP doesn't work but it should, temporarily disable + public static final Set INSTRUCTION_FILE_ROUNDTRIP_TEMP_UNSUPPORTED = + Set.of(PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3); + + // Ranged Get Supported Versions + public static final Set RANGED_GET_CURRENT_VERSIONS = + Set.of( + JAVA_V3_CURRENT + // CPP_V2_CURRENT + ); + + public static final Set RANGED_GET_TRANSITION_VERSIONS = + Set.of( + JAVA_V3_TRANSITION + // CPP_V2_TRANSITION + ); + + public static final Set RANGED_GET_IMPROVED_VERSIONS = + Set.of( + JAVA_V4 + // CPP_V3 + ); + public static final Set CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT, @@ -433,6 +459,34 @@ public static Stream crossLanguageClients() { ))); } + /** + * Get stream of arguments for current version clients which support ranged gets for testing. + */ + public static Stream rangedGetCurrentClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_CURRENT_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** + * Get stream of arguments for transition version clients for testing. + */ + public static Stream rangedGetTransitionClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_TRANSITION_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** + * Get stream of arguments for improved version clients for testing. + */ + public static Stream rangedGetImprovedClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_IMPROVED_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** * For a given string, append a suffix to distinguish it from * simultaneous test runs. @@ -512,6 +566,71 @@ public static void Decrypt( } } + public static void DecryptWithRangedGet( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + Random rand = new Random(); + for (String objectKey : crossLanguageObjects) { + // Get random range within the object length + int max = objectKey.length() - 1; + int begin = rand.nextInt(max), end = rand.nextInt(max - begin) + begin + 1; + String range = "bytes=" + begin + "-" + end; + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .range(range) + .key(objectKey) + .build()); + + // Then: Pass + assertTrue(MessageDigest.isEqual(objectKey.substring(begin, end + 1).getBytes(StandardCharsets.UTF_8), output.getBody().array())); + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + } + } + + + public static void DecryptWithRangedGet_fails( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + List successfulDecrypt = new ArrayList<>(); + Random rand = new Random(); + for (String objectKey : crossLanguageObjects) { + try { + + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + // Get random range within the object length + int max = objectKey.length() - 1; + int begin = rand.nextInt(max), end = rand.nextInt(max - begin) + begin + 1; + String range = "bytes=" + begin + "-" + end; + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .range(range) + .key(objectKey) + .build()); + // It should fail to decrypt + successfulDecrypt.add(objectKey); + } catch (S3EncryptionClientError e) { + // This is a success + // TODO, add the failure message + } + } + + assertEquals(successfulDecrypt.size(), 0, "Ranged get should have failed:" + String.join(",", successfulDecrypt)); + } + public static void Decrypt_fails( S3ECTestServerClient client, String S3ECId, List crossLanguageObjects, diff --git a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index e7c5493f..b7def958 100644 --- a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -37,6 +37,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index 86749489..155ee15e 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -39,6 +39,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index 17e9a8ee..c21c0ead 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -37,6 +37,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/model/object.smithy b/test-server/model/object.smithy index 6d793353..3ff1cf3c 100644 --- a/test-server/model/object.smithy +++ b/test-server/model/object.smithy @@ -80,6 +80,10 @@ operation GetObject { @required @notProperty clientID: String + + @httpHeader("Range") + @notProperty + range: String } output := for Object {