From f47eb5014aa99ffa9d22bbd1de023adfdfedb827 Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Tue, 4 Feb 2020 17:38:33 -0800 Subject: [PATCH 1/3] Making tests opt-out instead of opt-in and update TestVectorRunner JUnit5 doesn't support test suites yet (see https://github.com/junit-team/junit5/issues/744) and the existing test suites do not support the new JUnit5 tests that are being used for keyrings. This change removes the test suites, and configures Maven to include all tests except those marked with certain JUnit tags. Additionally, this change updates the TestVectorRunner to also test Keyrings and removes the redundant XCompat tests. --- pom.xml | 40 +++- .../examples/BasicEncryptionExampleTest.java | 3 + .../examples/EscrowedEncryptExampleTest.java | 3 + .../encryptionsdk/AllTestsSuite.java | 63 ----- .../encryptionsdk/AwsCryptoTest.java | 10 +- .../encryptionsdk/CryptoInputStreamTest.java | 3 +- .../encryptionsdk/CryptoOutputStreamTest.java | 6 +- .../encryptionsdk/FastTestsOnlySuite.java | 89 ------- .../encryptionsdk/IntegrationTestSuite.java | 15 -- .../encryptionsdk/SlowTestCategory.java | 14 -- .../amazonaws/encryptionsdk/TestUtils.java | 13 + .../encryptionsdk/TestVectorRunner.java | 178 +++++++------- .../encryptionsdk/XCompatDecryptTest.java | 225 ------------------ .../FrameEncryptionHandlerVeryLongTest.java | 15 +- .../MasterKeyProviderCompatibilityTest.java | 4 + .../KMSProviderBuilderIntegrationTests.java | 73 +++--- .../kms/XCompatKmsDecryptTest.java | 115 --------- 17 files changed, 208 insertions(+), 661 deletions(-) delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/FastTestsOnlySuite.java delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/SlowTestCategory.java delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/XCompatDecryptTest.java delete mode 100644 src/test/java/com/amazonaws/encryptionsdk/kms/XCompatKmsDecryptTest.java diff --git a/pom.xml b/pom.xml index a8774878b..8ed83317f 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ org.junit.jupiter - junit-jupiter-engine + junit-jupiter 5.5.2 test @@ -208,20 +208,17 @@ maven-surefire-plugin 2.22.0 - - **/AllTestsSuite.java - + slow + fast-tests-only - - false - @@ -229,9 +226,32 @@ maven-surefire-plugin 2.22.0 - - **/FastTestsOnlySuite.java - + slow, integration + + true + + + 120 + + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + integration diff --git a/src/test/java/com/amazonaws/crypto/examples/BasicEncryptionExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/BasicEncryptionExampleTest.java index 1e63f4d56..95405fa2b 100644 --- a/src/test/java/com/amazonaws/crypto/examples/BasicEncryptionExampleTest.java +++ b/src/test/java/com/amazonaws/crypto/examples/BasicEncryptionExampleTest.java @@ -13,10 +13,13 @@ package com.amazonaws.crypto.examples; +import com.amazonaws.encryptionsdk.TestUtils; import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +@Tag(TestUtils.TAG_INTEGRATION) class BasicEncryptionExampleTest { @Test diff --git a/src/test/java/com/amazonaws/crypto/examples/EscrowedEncryptExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/EscrowedEncryptExampleTest.java index a7d49878c..6e3cf5137 100644 --- a/src/test/java/com/amazonaws/crypto/examples/EscrowedEncryptExampleTest.java +++ b/src/test/java/com/amazonaws/crypto/examples/EscrowedEncryptExampleTest.java @@ -13,12 +13,15 @@ package com.amazonaws.crypto.examples; +import com.amazonaws.encryptionsdk.TestUtils; import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import java.security.GeneralSecurityException; +@Tag(TestUtils.TAG_INTEGRATION) class EscrowedEncryptExampleTest { @Test diff --git a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java deleted file mode 100644 index f16681a60..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.amazonaws.encryptionsdk; - -import com.amazonaws.encryptionsdk.jce.JceMasterKeyTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import com.amazonaws.encryptionsdk.caching.CacheIdentifierTests; -import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManagerTest; -import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCacheTest; -import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCacheThreadStormTest; -import com.amazonaws.encryptionsdk.caching.NullCryptoMaterialsCacheTest; -import com.amazonaws.encryptionsdk.internal.BlockDecryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.BlockEncryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.CipherHandlerTest; -import com.amazonaws.encryptionsdk.internal.DecryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.EncContextSerializerTest; -import com.amazonaws.encryptionsdk.internal.EncryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.FrameDecryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.FrameEncryptionHandlerTest; -import com.amazonaws.encryptionsdk.internal.PrimitivesParserTest; -import com.amazonaws.encryptionsdk.jce.KeyStoreProviderTest; -import com.amazonaws.encryptionsdk.model.CipherBlockHeadersTest; -import com.amazonaws.encryptionsdk.model.CipherFrameHeadersTest; -import com.amazonaws.encryptionsdk.model.KeyBlobTest; -import com.amazonaws.encryptionsdk.model.DecryptionMaterialsRequestTest; -import com.amazonaws.encryptionsdk.multi.MultipleMasterKeyTest; -import com.amazonaws.encryptionsdk.kms.KMSProviderBuilderMockTests; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - BlockDecryptionHandlerTest.class, - BlockEncryptionHandlerTest.class, - CipherHandlerTest.class, - DecryptionHandlerTest.class, - EncContextSerializerTest.class, - EncryptionHandlerTest.class, - FrameDecryptionHandlerTest.class, - FrameEncryptionHandlerTest.class, - PrimitivesParserTest.class, - KeyStoreProviderTest.class, - CipherBlockHeadersTest.class, - CipherFrameHeadersTest.class, - KeyBlobTest.class, - DecryptionMaterialsRequestTest.class, - MultipleMasterKeyTest.class, - AwsCryptoTest.class, - CryptoInputStreamTest.class, - CryptoOutputStreamTest.class, - TestVectorRunner.class, - XCompatDecryptTest.class, - DefaultCryptoMaterialsManagerTest.class, - NullCryptoMaterialsCacheTest.class, - CacheIdentifierTests.class, - CachingCryptoMaterialsManagerTest.class, - LocalCryptoMaterialsCacheTest.class, - LocalCryptoMaterialsCacheThreadStormTest.class, - UtilsTest.class, - MultipleMasterKeyTest.class, - KMSProviderBuilderMockTests.class, - JceMasterKeyTest.class -}) -public class AllTestsSuite { -} diff --git a/src/test/java/com/amazonaws/encryptionsdk/AwsCryptoTest.java b/src/test/java/com/amazonaws/encryptionsdk/AwsCryptoTest.java index 6677b805a..7da0fd8a0 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/AwsCryptoTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/AwsCryptoTest.java @@ -13,9 +13,9 @@ package com.amazonaws.encryptionsdk; -import static com.amazonaws.encryptionsdk.FastTestsOnlySuite.isFastTestSuiteActive; import static com.amazonaws.encryptionsdk.TestUtils.assertNullChecks; import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; +import static com.amazonaws.encryptionsdk.TestUtils.isFastTestsOnly; import static java.util.Collections.singletonMap; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -203,7 +203,7 @@ public void encryptDecrypt() { for (int j = 0; j < bytesToTest.length; j++) { final int byteSize = bytesToTest[j]; - if (byteSize > 500_000 && isFastTestSuiteActive()) { + if (byteSize > 500_000 && isFastTestsOnly()) { continue; } @@ -232,7 +232,7 @@ public void encryptDecryptWithBadSignature() { for (int j = 0; j < bytesToTest.length; j++) { final int byteSize = bytesToTest[j]; - if (byteSize > 500_000 && isFastTestSuiteActive()) { + if (byteSize > 500_000 && isFastTestsOnly()) { continue; } @@ -258,7 +258,7 @@ public void encryptDecryptWithParsedCiphertext() { for (int j = 0; j < bytesToTest.length; j++) { final int byteSize = bytesToTest[j]; - if (byteSize > 500_000 && isFastTestSuiteActive()) { + if (byteSize > 500_000 && isFastTestsOnly()) { continue; } @@ -467,7 +467,7 @@ public void estimateCiphertextSize() { for (int j = 0; j < bytesToTest.length; j++) { final int byteSize = bytesToTest[j]; - if (byteSize > 500_000 && isFastTestSuiteActive()) { + if (byteSize > 500_000 && isFastTestsOnly()) { continue; } diff --git a/src/test/java/com/amazonaws/encryptionsdk/CryptoInputStreamTest.java b/src/test/java/com/amazonaws/encryptionsdk/CryptoInputStreamTest.java index 6762475e6..7bca94cd9 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/CryptoInputStreamTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/CryptoInputStreamTest.java @@ -15,6 +15,7 @@ import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; import static com.amazonaws.encryptionsdk.TestUtils.insecureRandomBytes; +import static com.amazonaws.encryptionsdk.TestUtils.isFastTestsOnly; import static com.amazonaws.encryptionsdk.internal.TestIOUtils.getSha256Hash; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -163,7 +164,7 @@ public static Collection encryptDecryptParams() { // Our bytesToTest and readLenVals arrays tend to have the bigger numbers towards the end - we'll chop off // the last few as they take the longest and don't really add that much more coverage. int skipLastNSizes; - if (!FastTestsOnlySuite.isFastTestSuiteActive()) { + if (!isFastTestsOnly()) { skipLastNSizes = 0; } else if (firstAlgorithm) { // We'll run more tests for the first algorithm in the list - but not go quite so far as running the diff --git a/src/test/java/com/amazonaws/encryptionsdk/CryptoOutputStreamTest.java b/src/test/java/com/amazonaws/encryptionsdk/CryptoOutputStreamTest.java index 558dc88b6..f31a2849a 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/CryptoOutputStreamTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/CryptoOutputStreamTest.java @@ -14,9 +14,9 @@ package com.amazonaws.encryptionsdk; import static com.amazonaws.encryptionsdk.AwsCrypto.getDefaultFrameSize; -import static com.amazonaws.encryptionsdk.FastTestsOnlySuite.isFastTestSuiteActive; import static com.amazonaws.encryptionsdk.TestUtils.assertThrows; import static com.amazonaws.encryptionsdk.TestUtils.insecureRandomBytes; +import static com.amazonaws.encryptionsdk.TestUtils.isFastTestsOnly; import static com.amazonaws.encryptionsdk.TestUtils.toByteArray; import static com.amazonaws.encryptionsdk.internal.TestIOUtils.getSha256Hash; import static org.junit.Assert.assertArrayEquals; @@ -163,7 +163,7 @@ public static Collection encryptDecryptParams() { int[] bytesToTest = { 0, 1, frameSize - 1, frameSize, frameSize + 1, (int) (frameSize * 1.5), frameSize * 2, 1000000 }; - if (isFastTestSuiteActive()) { + if (isFastTestsOnly()) { // Exclude the last two sizes, as they're the slowest bytesToTest = Arrays.copyOfRange(bytesToTest, 0, bytesToTest.length - 2); } @@ -173,7 +173,7 @@ public static Collection encryptDecryptParams() { final int byteSize = bytesToTest[j]; int[] readLenVals = { byteSize - 1, byteSize, byteSize + 1, byteSize * 2, 1000000 }; - if (isFastTestSuiteActive()) { + if (isFastTestsOnly()) { // Only test one read() call buffer length in the fast tests. This greatly cuts down on // the combinatorial explosion of test cases here. readLenVals = Arrays.copyOfRange(readLenVals, 0, 1); diff --git a/src/test/java/com/amazonaws/encryptionsdk/FastTestsOnlySuite.java b/src/test/java/com/amazonaws/encryptionsdk/FastTestsOnlySuite.java deleted file mode 100644 index 528ae273e..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/FastTestsOnlySuite.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.amazonaws.encryptionsdk; - -import java.util.concurrent.TimeUnit; - -import org.junit.ClassRule; -import org.junit.experimental.categories.Categories; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.junit.runner.Description; -import org.junit.runner.RunWith; -import org.junit.runner.Runner; -import org.junit.runners.Suite; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.RunnerBuilder; -import org.junit.runners.model.Statement; - -/** - * This test suite is intended to assist in rapid development; it filters out some of the slower, more exhaustive tests - * in the overall test suite to allow for a rapid edit-test cycle. - */ -@RunWith(FastTestsOnlySuite.CustomRunner.class) -@Suite.SuiteClasses({ - AllTestsSuite.class -}) -@Categories.ExcludeCategory(SlowTestCategory.class) -public class FastTestsOnlySuite { - private static InheritableThreadLocal IS_FAST_TEST_SUITE_ACTIVE = new InheritableThreadLocal() { - @Override protected Boolean initialValue() { - return false; - } - }; - - // This method is used to adjust DataProviders to provide a smaller subset of their test cases when the fast tests - // are selected - public static boolean isFastTestSuiteActive() { - return IS_FAST_TEST_SUITE_ACTIVE.get(); - } - - // Require that this fast suite completes relatively quickly. If you're seeing this timeout get hit, it's time to - // pare down tests some more. As a general rule of thumb, we should avoid any single test taking more than 10s, and - // try to keep the number of such slow tests to a minimum. - @ClassRule - public static Timeout timeout = new Timeout(2, TimeUnit.MINUTES); - - @ClassRule - public static EnableFastSuite enableFastSuite = new EnableFastSuite(); - - // TestRules run over the execution of tests, but not over the generation of parameterized test data... - private static class EnableFastSuite implements TestRule { - @Override public Statement apply( - Statement base, Description description - ) { - return new Statement() { - @Override public void evaluate() throws Throwable { - Boolean oldValue = IS_FAST_TEST_SUITE_ACTIVE.get(); - - try { - IS_FAST_TEST_SUITE_ACTIVE.set(true); - base.evaluate(); - } finally { - IS_FAST_TEST_SUITE_ACTIVE.set(oldValue); - } - } - }; - } - } - - // ... so we also need a custom TestRunner that will pass the flag on to the parameterized test data generators. - public static class CustomRunner extends Categories { - public CustomRunner(Class klass, RunnerBuilder builder) throws InitializationError { - super( - klass, - new RunnerBuilder() { - @Override public Runner runnerForClass(Class testClass) throws Throwable { - Boolean oldValue = IS_FAST_TEST_SUITE_ACTIVE.get(); - - try { - IS_FAST_TEST_SUITE_ACTIVE.set(true); - Runner r = builder.runnerForClass(testClass); - return r; - } finally { - IS_FAST_TEST_SUITE_ACTIVE.set(oldValue); - } - } - } - ); - } - } -} diff --git a/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java b/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java deleted file mode 100644 index 44628b0db..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/IntegrationTestSuite.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.amazonaws.encryptionsdk; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import com.amazonaws.encryptionsdk.kms.KMSProviderBuilderIntegrationTests; -import com.amazonaws.encryptionsdk.kms.XCompatKmsDecryptTest; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - XCompatKmsDecryptTest.class, - KMSProviderBuilderIntegrationTests.class -}) -public class IntegrationTestSuite { -} diff --git a/src/test/java/com/amazonaws/encryptionsdk/SlowTestCategory.java b/src/test/java/com/amazonaws/encryptionsdk/SlowTestCategory.java deleted file mode 100644 index 9814b0948..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/SlowTestCategory.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.amazonaws.encryptionsdk; - -/** - * JUnit category marking tests to be excluded from the FastTestsOnlySuite. Usage: - * - * @Category(SlowTestCategory.class) - * @Test - * public void mySlowTest() { - * // encrypt a couple terabytes of test data - * } - * - * - */ -public interface SlowTestCategory {} diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java b/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java index 6763798f9..36d616e30 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java @@ -34,6 +34,15 @@ private static byte[] ensureRandomCached(int length) { }); } + /** + * JUnit tag name marking tests or test classes to be excluded from normal test profiles + */ + public static final String TAG_SLOW_TEST = "slow"; + /** + * JUnit tag name marking integration tests + */ + public static final String TAG_INTEGRATION = "integration"; + @FunctionalInterface public interface ThrowingRunnable { void run() throws Throwable; @@ -211,4 +220,8 @@ public static int[] signedBytesToUnsignedBytes(final byte[] signedBytes) { return unsignedBytes; } + + public static boolean isFastTestsOnly() { + return Boolean.parseBoolean(System.getProperty("fastTestsOnly")); + } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java index 14019c2e2..5adbb4f96 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java @@ -1,25 +1,40 @@ -package com.amazonaws.encryptionsdk; +/* + * Copyright 2020 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. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ -import static java.lang.String.format; +package com.amazonaws.encryptionsdk; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.encryptionsdk.jce.JceMasterKey; +import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; +import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier; +import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory; import com.amazonaws.util.IOUtils; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.bouncycastle.util.encoders.Base64; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.net.JarURLConnection; import java.net.URL; import java.security.GeneralSecurityException; @@ -38,32 +53,41 @@ import java.util.jar.JarFile; import java.util.zip.ZipEntry; -@RunWith(Parameterized.class) -public class TestVectorRunner { - // We save the files in memory to avoid repeatedly retrieving them. This won't work if the plaintexts are too - // large or numerous +import static java.lang.String.format; +import static java.util.Collections.emptyList; +import static org.apache.commons.lang3.Validate.isTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +@Tag(TestUtils.TAG_INTEGRATION) +class TestVectorRunner { + // We save the files in memory to avoid repeatedly retrieving them. + // This won't work if the plaintexts are too large or numerous private static final Map cachedData = new HashMap<>(); - - private final String testName; - private final TestCase testCase; - - public TestVectorRunner(final String testName, TestCase testCase) { - this.testName = testName; - this.testCase = testCase; - } - - @Test - public void decrypt() { + private static final AwsKmsClientSupplier awsKmsClientSupplier = AwsKmsClientSupplier.builder() + .credentialsProvider(new DefaultAWSCredentialsProviderChain()) + .clientCaching(true) + .build(); + private static final KmsMasterKeyProvider kmsProv = KmsMasterKeyProvider + .builder() + .withCustomClientFactory(awsKmsClientSupplier::getClient) + .build(); + + @ParameterizedTest(name = "Compatibility Test: {0}") + @MethodSource("data") + void decrypt(TestCase testCase) { AwsCrypto crypto = new AwsCrypto(); - byte[] plaintext = crypto.decryptData(testCase.mkp, cachedData.get(testCase.ciphertextPath)).getResult(); + byte[] keyringPlaintext = crypto.decrypt(DecryptRequest.builder() + .ciphertext(cachedData.get(testCase.ciphertextPath)) + .keyring(testCase.keyring).build()).getResult(); + byte[] mkpPlaintext = crypto.decryptData(testCase.mkp, cachedData.get(testCase.ciphertextPath)).getResult(); final byte[] expectedPlaintext = cachedData.get(testCase.plaintextPath); - Assert.assertArrayEquals(expectedPlaintext, plaintext); + assertArrayEquals(expectedPlaintext, keyringPlaintext); + assertArrayEquals(expectedPlaintext, mkpPlaintext); } - @Parameterized.Parameters(name="Compatibility Test: {0}") @SuppressWarnings("unchecked") - public static Collection data() throws Exception { + static Collection data() throws Exception { final String zipPath = System.getProperty("testVectorZip"); if (zipPath == null) { return Collections.emptyList(); @@ -73,43 +97,33 @@ public static Collection data() throws Exception { try (JarFile jar = jarConnection.getJarFile()) { final Map manifest = readJsonMapFromJar(jar, "manifest.json"); - final Map metaData = (Map) manifest.get("manifest"); // We only support "awses-decrypt" type manifests right now - if (!"awses-decrypt".equals(metaData.get("type"))) { - throw new IllegalArgumentException("Unsupported manifest type: " + metaData.get("type")); - } - - if (!Integer.valueOf(1).equals(metaData.get("version"))) { - throw new IllegalArgumentException("Unsupported manifest version: " + metaData.get("version")); - } + isTrue("awses-decrypt".equals(metaData.get("type")), "Unsupported manifest type: %s", metaData.get("type")); + isTrue(Integer.valueOf(1).equals(metaData.get("version")), "Unsupported manifest version: %s", metaData.get("version")); final Map keys = parseKeyManifest(readJsonMapFromJar(jar, (String) manifest.get("keys"))); - final KmsMasterKeyProvider kmsProv = KmsMasterKeyProvider - .builder() - .withCredentials(new DefaultAWSCredentialsProviderChain()) - .build(); + final List testCases = new ArrayList<>(); + + ((Map>) manifest.get("tests")).forEach( + (testName, data) -> testCases.add(parseTest(testName, data, keys, jar))); - List testCases = new ArrayList<>(); - for (Map.Entry> testEntry : - ((Map>) manifest.get("tests")).entrySet()) { - testCases.add(new Object[]{testEntry.getKey(), - parseTest(testEntry.getKey(), testEntry.getValue(), keys, jar, kmsProv)}); - } return testCases; } } - @AfterClass - public static void teardown() { + @AfterAll + static void teardown() { cachedData.clear(); } - private static byte[] readBytesFromJar(JarFile jar, String fileName) throws IOException { + private static byte[] readBytesFromJar(JarFile jar, String fileName) { try (InputStream is = readFromJar(jar, fileName)) { return IOUtils.toByteArray(is); + } catch (IOException ex) { + throw new UncheckedIOException(ex); } } @@ -126,21 +140,15 @@ private static InputStream readFromJar(JarFile jar, String name) throws IOExcept return jar.getInputStream(entry); } - private static void cacheData(JarFile jar, String url) throws IOException { - if (!cachedData.containsKey(url)) { - cachedData.put(url, readBytesFromJar(jar, url)); - } - } - @SuppressWarnings("unchecked") private static TestCase parseTest(String testName, Map data, Map keys, - JarFile jar, KmsMasterKeyProvider kmsProv) throws IOException { + JarFile jar) { final String plaintextUrl = (String) data.get("plaintext"); - cacheData(jar, plaintextUrl); final String ciphertextURL = (String) data.get("ciphertext"); - cacheData(jar, ciphertextURL); + cachedData.putIfAbsent(plaintextUrl, readBytesFromJar(jar, plaintextUrl)); + cachedData.putIfAbsent(ciphertextURL, readBytesFromJar(jar, ciphertextURL)); - @SuppressWarnings("generic") + final List keyrings = new ArrayList<>(); final List> mks = new ArrayList<>(); for (Map mkEntry : (List>) data.get("master-keys")) { @@ -149,11 +157,19 @@ private static TestCase parseTest(String testName, Map data, Map final KeyEntry key = keys.get(keyName); if ("aws-kms".equals(type)) { + keyrings.add(StandardKeyrings.awsKms() + .awsKmsClientSupplier(awsKmsClientSupplier) + .generatorKeyId(AwsKmsCmkId.fromString(key.keyId)) + .build()); mks.add(kmsProv.getMasterKey(key.keyId)); } else if ("raw".equals(type)) { final String provId = mkEntry.get("provider-id"); final String algorithm = mkEntry.get("encryption-algorithm"); if ("aes".equals(algorithm)) { + keyrings.add(StandardKeyrings.rawAes() + .keyName(key.keyId) + .keyNamespace(provId) + .wrappingKey((SecretKey) key.key).build()); mks.add(JceMasterKey.getInstance((SecretKey) key.key, provId, key.keyId, "AES/GCM/NoPadding")); } else if ("rsa".equals(algorithm)) { String transformation = "RSA/ECB/"; @@ -162,21 +178,27 @@ private static TestCase parseTest(String testName, Map data, Map transformation += "PKCS1Padding"; } else if ("oaep-mgf1".equals(padding)) { final String hashName = mkEntry.get("padding-hash") - .replace("sha", "sha-") - .toUpperCase(); + .replace("sha", "sha-") + .toUpperCase(); transformation += "OAEPWith" + hashName + "AndMGF1Padding"; } else { throw new IllegalArgumentException("Unsupported padding:" + padding); } final PublicKey wrappingKey; final PrivateKey unwrappingKey; - if (key.key instanceof PublicKey) { + if (key.key instanceof PublicKey) { wrappingKey = (PublicKey) key.key; unwrappingKey = null; } else { wrappingKey = null; unwrappingKey = (PrivateKey) key.key; } + keyrings.add(StandardKeyrings.rawRsa() + .publicKey(wrappingKey) + .privateKey(unwrappingKey) + .keyNamespace(provId) + .keyName(key.keyId) + .wrappingAlgorithm(transformation).build()); mks.add(JceMasterKey.getInstance(wrappingKey, unwrappingKey, provId, key.keyId, transformation)); } else { throw new IllegalArgumentException("Unsupported algorithm: " + algorithm); @@ -186,11 +208,11 @@ private static TestCase parseTest(String testName, Map data, Map } } - return new TestCase(testName, ciphertextURL, plaintextUrl, mks); + return new TestCase(testName, ciphertextURL, plaintextUrl, keyrings, mks); } @SuppressWarnings("unchecked") - private static Map parseKeyManifest(final Map keysManifest) throws GeneralSecurityException { + static Map parseKeyManifest(final Map keysManifest) throws GeneralSecurityException { // check our type final Map metaData = (Map) keysManifest.get("manifest"); if (!"keys".equals(metaData.get("type"))) { @@ -221,8 +243,7 @@ private static Map parseKeyManifest(final Map if (!"base64".equals(encoding)) { throw new IllegalArgumentException(format("Key %s is symmetric but has encoding %s", keyId, encoding)); } - keyEntry = new KeyEntry(name, keyId, keyType, - new SecretKeySpec(Base64.decode(material), algorithm.toUpperCase())); + keyEntry = new KeyEntry(keyId, new SecretKeySpec(Base64.decode(material), algorithm.toUpperCase())); break; case "private": kf = KeyFactory.getInstance(algorithm); @@ -230,8 +251,7 @@ private static Map parseKeyManifest(final Map throw new IllegalArgumentException(format("Key %s is private but has encoding %s", keyId, encoding)); } byte[] pkcs8Key = parsePem(material); - keyEntry = new KeyEntry(name, keyId, keyType, - kf.generatePrivate(new PKCS8EncodedKeySpec(pkcs8Key))); + keyEntry = new KeyEntry(keyId, kf.generatePrivate(new PKCS8EncodedKeySpec(pkcs8Key))); break; case "public": kf = KeyFactory.getInstance(algorithm); @@ -239,11 +259,10 @@ private static Map parseKeyManifest(final Map throw new IllegalArgumentException(format("Key %s is private but has encoding %s", keyId, encoding)); } byte[] x509Key = parsePem(material); - keyEntry = new KeyEntry(name, keyId, keyType, - kf.generatePublic(new X509EncodedKeySpec(x509Key))); + keyEntry = new KeyEntry(keyId, kf.generatePublic(new X509EncodedKeySpec(x509Key))); break; case "aws-kms": - keyEntry = new KeyEntry(name, keyId, keyType, null); + keyEntry = new KeyEntry(keyId, null); break; default: throw new IllegalArgumentException("Unsupported key type: " + keyType); @@ -261,15 +280,11 @@ private static byte[] parsePem(String pem) { } private static class KeyEntry { - final String name; final String keyId; - final String type; final Key key; - private KeyEntry(String name, String keyId, String type, Key key) { - this.name = name; + private KeyEntry(String keyId, Key key) { this.keyId = keyId; - this.type = type; this.key = key; } } @@ -278,17 +293,20 @@ private static class TestCase { private final String name; private final String ciphertextPath; private final String plaintextPath; + private final Keyring keyring; private final MasterKeyProvider mkp; - private TestCase(String name, String ciphertextPath, String plaintextPath, List> mks) { - this(name, ciphertextPath, plaintextPath, MultipleProviderFactory.buildMultiProvider(mks)); - } - - private TestCase(String name, String ciphertextPath, String plaintextPath, MasterKeyProvider mkp) { + private TestCase(String name, String ciphertextPath, String plaintextPath, List keyrings, List> mks) { this.name = name; this.ciphertextPath = ciphertextPath; this.plaintextPath = plaintextPath; - this.mkp = mkp; + this.keyring = StandardKeyrings.multi(keyrings.get(0), keyrings.size() > 1 ? keyrings.subList(1, keyrings.size()) : emptyList()); + this.mkp = MultipleProviderFactory.buildMultiProvider(mks); + } + + @Override + public String toString() { + return name; } } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/XCompatDecryptTest.java b/src/test/java/com/amazonaws/encryptionsdk/XCompatDecryptTest.java deleted file mode 100644 index 9e7a278a4..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/XCompatDecryptTest.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2016 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. A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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 com.amazonaws.encryptionsdk; - -import java.io.File; -import java.io.StringReader; -import java.lang.IllegalArgumentException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.lang3.StringUtils; - -import org.bouncycastle.util.io.pem.PemReader; - -import static org.junit.Assert.assertArrayEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import com.amazonaws.encryptionsdk.internal.Utils; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.core.type.TypeReference; - -import com.amazonaws.encryptionsdk.jce.JceMasterKey; -import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory; - -@RunWith(Parameterized.class) -public class XCompatDecryptTest { - private static final String STATIC_XCOMPAT_NAME = "static-aws-xcompat"; - private static final String AES_GCM = "AES/GCM/NoPadding"; - - private String plaintextFileName; - private String ciphertextFileName; - private MasterKeyProvider masterKeyProvider; - - public XCompatDecryptTest( - String plaintextFileName, - String ciphertextFileName, - MasterKeyProvider masterKeyProvider - ) throws Exception { - this.plaintextFileName = plaintextFileName; - this.ciphertextFileName = ciphertextFileName; - this.masterKeyProvider = masterKeyProvider; - } - - @Parameters(name="{index}: testDecryptFromFile({0}, {1}, {2})") - public static Collection data() throws Exception{ - String baseDirName; - baseDirName = System.getProperty("staticCompatibilityResourcesDir"); - if (baseDirName == null) { - baseDirName = - XCompatDecryptTest.class.getProtectionDomain().getCodeSource().getLocation().getPath() + - "aws_encryption_sdk_resources"; - } - - List testCases_ = new ArrayList(); - - String ciphertextManifestName = StringUtils.join( - new String[]{ - baseDirName, - "manifests", - "ciphertext.manifest" - }, - File.separator - ); - File ciphertextManifestFile = new File(ciphertextManifestName); - - if (!ciphertextManifestFile.exists()) { - return Collections.emptySet(); - } - - ObjectMapper ciphertextManifestMapper = new ObjectMapper(); - Map ciphertextManifest = ciphertextManifestMapper.readValue( - ciphertextManifestFile, - new TypeReference>(){} - ); - - HashMap> staticKeyMap = new HashMap>(); - - Map testKeys = (Map)ciphertextManifest.get("test_keys"); - - for (Map.Entry keyType : testKeys.entrySet()) { - Map keys = (Map)keyType.getValue(); - HashMap thisKeyType = new HashMap(); - for (Map.Entry key : keys.entrySet()) { - Map thisKey = (Map)key.getValue(); - String keyRaw = new String( - StringUtils.join( - (List)thisKey.get("key"), - (String)thisKey.getOrDefault("line_separator", "") - ).getBytes(), - StandardCharsets.UTF_8 - ); - byte[] keyBytes; - switch ((String)thisKey.get("encoding")) { - case "base64": - keyBytes = Utils.decodeBase64String(keyRaw); - break; - case "pem": - PemReader pemReader = new PemReader(new StringReader(keyRaw)); - keyBytes = pemReader.readPemObject().getContent(); - break; - case "raw": - default: - keyBytes = keyRaw.getBytes(); - } - thisKeyType.put((String)key.getKey(), keyBytes); - } - staticKeyMap.put((String)keyType.getKey(), thisKeyType); - } - - final KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA"); - - List> testCases = (List>)ciphertextManifest.get("test_cases"); - for (Map testCase : testCases) { - Map plaintext = (Map)testCase.get("plaintext"); - Map ciphertext = (Map)testCase.get("ciphertext"); - - short algId = (short) Integer.parseInt((String)testCase.get("algorithm"), 16); - CryptoAlgorithm encryptionAlgorithm = CryptoAlgorithm.deserialize(algId); - - List> masterKeys = (List>)testCase.get("master_keys"); - List allMasterKeys = new ArrayList(); - for (Map aMasterKey : masterKeys) { - String providerId = (String)aMasterKey.get("provider_id"); - if (providerId.equals(STATIC_XCOMPAT_NAME) && (boolean)aMasterKey.get("decryptable")) { - String paddingAlgorithm = (String)aMasterKey.getOrDefault("padding_algorithm", ""); - String paddingHash = (String)aMasterKey.getOrDefault("padding_hash", ""); - Integer keyBits = (Integer)aMasterKey.getOrDefault( - "key_bits", - encryptionAlgorithm.getDataKeyLength() * 8 - ); - String keyId = - (String)aMasterKey.get("encryption_algorithm") + "." + - keyBits.toString() + "." + - paddingAlgorithm + "." + - paddingHash; - String encAlg = (String)aMasterKey.get("encryption_algorithm"); - switch (encAlg.toUpperCase()) { - case "RSA": - String cipherBase = "RSA/ECB/"; - String cipherName; - switch (paddingAlgorithm) { - case "OAEP-MGF1": - cipherName = cipherBase + "OAEPWith" + paddingHash + "AndMGF1Padding"; - break; - case "PKCS1": - cipherName = cipherBase + paddingAlgorithm + "Padding"; - break; - default: - throw new IllegalArgumentException("Unknown padding algorithm: " + paddingAlgorithm); - } - PrivateKey privKey = rsaKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(staticKeyMap.get("RSA").get(keyBits.toString()))); - allMasterKeys.add(JceMasterKey.getInstance( - null, - privKey, - STATIC_XCOMPAT_NAME, - keyId, - cipherName - )); - break; - case "AES": - SecretKeySpec spec = new SecretKeySpec( - staticKeyMap.get("AES").get(keyBits.toString()), - 0, - encryptionAlgorithm.getDataKeyLength(), - encryptionAlgorithm.getDataKeyAlgo() - ); - allMasterKeys.add(JceMasterKey.getInstance(spec, STATIC_XCOMPAT_NAME, keyId, AES_GCM)); - break; - default: - throw new IllegalArgumentException("Unknown encryption algorithm: " + encAlg.toUpperCase()); - } - } - } - - if (allMasterKeys.size() > 0) { - final MasterKeyProvider provider = MultipleProviderFactory.buildMultiProvider(allMasterKeys); - testCases_.add(new Object[]{ - baseDirName + File.separator + plaintext.get("filename"), - baseDirName + File.separator + ciphertext.get("filename"), - provider - }); - } - } - return testCases_; - } - - @Test - public void testDecryptFromFile() throws Exception { - AwsCrypto crypto = new AwsCrypto(); - byte ciphertextBytes[] = Files.readAllBytes(Paths.get(ciphertextFileName)); - byte plaintextBytes[] = Files.readAllBytes(Paths.get(plaintextFileName)); - final CryptoResult decryptResult = crypto.decryptData( - masterKeyProvider, - ciphertextBytes - ); - assertArrayEquals(plaintextBytes, (byte[])decryptResult.getResult()); - } -} diff --git a/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java b/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java index 228bcc28f..8a335d608 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java @@ -1,28 +1,29 @@ package com.amazonaws.encryptionsdk.internal; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.fail; - import javax.crypto.spec.SecretKeySpec; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; +import com.amazonaws.encryptionsdk.TestUtils; import org.bouncycastle.util.encoders.Hex; -import org.bouncycastle.util.encoders.HexTranslator; -import org.junit.Test; import com.amazonaws.encryptionsdk.CryptoAlgorithm; import com.amazonaws.encryptionsdk.model.CipherFrameHeaders; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.fail; /* * This test exhaustively encrypts a 2^32 frame message, which takes approximately 2-3 hours on my hardware. Because of * this long test time, this test is not run as part of the normal suites. */ -public class FrameEncryptionHandlerVeryLongTest { +@Tag(TestUtils.TAG_SLOW_TEST) +class FrameEncryptionHandlerVeryLongTest { @Test - public void exhaustiveIVCheck() throws Exception { + void exhaustiveIVCheck() throws Exception { CryptoAlgorithm algorithm = CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_NO_KDF; FrameEncryptionHandler frameEncryptionHandler_ = new FrameEncryptionHandler( new SecretKeySpec(new byte[16], "AES"), diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java index 655fca396..4a4593d98 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java @@ -19,6 +19,7 @@ import com.amazonaws.encryptionsdk.DecryptRequest; import com.amazonaws.encryptionsdk.EncryptRequest; import com.amazonaws.encryptionsdk.MasterKeyProvider; +import com.amazonaws.encryptionsdk.TestUtils; import com.amazonaws.encryptionsdk.internal.RandomBytesGenerator; import com.amazonaws.encryptionsdk.internal.Utils; import com.amazonaws.encryptionsdk.jce.JceMasterKey; @@ -27,6 +28,7 @@ import com.amazonaws.encryptionsdk.kms.KmsMasterKey; import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import javax.crypto.SecretKey; @@ -46,6 +48,7 @@ class MasterKeyProviderCompatibilityTest { private static final byte[] PLAINTEXT = RandomBytesGenerator.generate(1000); private final AwsCrypto awsCrypto = new AwsCrypto(); + @Tag(TestUtils.TAG_INTEGRATION) @Test void testAwsKmsKeyringCompatibility() { MasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -89,6 +92,7 @@ void testRawRsaKeyringCompatibility() throws Exception { testCompatibility(keyring, mkp); } + @Tag(TestUtils.TAG_INTEGRATION) @Test void testMultiKeyringCompatibility() { SecretKey key = generateRandomKey(); diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSProviderBuilderIntegrationTests.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSProviderBuilderIntegrationTests.java index 1a58496dd..7d3062e67 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSProviderBuilderIntegrationTests.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSProviderBuilderIntegrationTests.java @@ -1,10 +1,10 @@ package com.amazonaws.encryptionsdk.kms; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; @@ -19,7 +19,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; +import com.amazonaws.encryptionsdk.TestUtils; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import com.amazonaws.AbortedException; @@ -41,9 +43,10 @@ import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; -public class KMSProviderBuilderIntegrationTests { +@Tag(TestUtils.TAG_INTEGRATION) +class KMSProviderBuilderIntegrationTests { @Test - public void whenBogusRegionsDecrypted_doesNotLeakClients() throws Exception { + void whenBogusRegionsDecrypted_doesNotLeakClients() { AtomicReference> kmsCache = new AtomicReference<>(); KmsMasterKeyProvider mkp = (new KmsMasterKeyProvider.Builder() { @@ -75,7 +78,7 @@ public void whenBogusRegionsDecrypted_doesNotLeakClients() throws Exception { } @Test - public void whenOperationSuccessful_clientIsCached() { + void whenOperationSuccessful_clientIsCached() { AtomicReference> kmsCache = new AtomicReference<>(); KmsMasterKeyProvider mkp = (new KmsMasterKeyProvider.Builder() { @@ -99,7 +102,7 @@ public void whenOperationSuccessful_clientIsCached() { } @Test - public void whenConstructedWithoutArguments_canUseMultipleRegions() throws Exception { + void whenConstructedWithoutArguments_canUseMultipleRegions() { KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder().build(); for (String key : KMSTestFixtures.TEST_KEY_IDS) { @@ -115,25 +118,27 @@ public void whenConstructedWithoutArguments_canUseMultipleRegions() throws Excep } } - @SuppressWarnings("deprecation") @Test(expected = CannotUnwrapDataKeyException.class) - public void whenLegacyConstructorsUsed_multiRegionDecryptIsNotSupported() throws Exception { + @SuppressWarnings("deprecation") @Test + void whenLegacyConstructorsUsed_multiRegionDecryptIsNotSupported() { KmsMasterKeyProvider mkp = new KmsMasterKeyProvider(); - for (String key : KMSTestFixtures.TEST_KEY_IDS) { - byte[] ciphertext = - new AwsCrypto().encryptData( - KmsMasterKeyProvider.builder() - .withKeysForEncryption(key) - .build(), - new byte[1] - ).getResult(); - - new AwsCrypto().decryptData(mkp, ciphertext); - } + assertThrows(CannotUnwrapDataKeyException.class, () -> { + for (String key : KMSTestFixtures.TEST_KEY_IDS) { + byte[] ciphertext = + new AwsCrypto().encryptData( + KmsMasterKeyProvider.builder() + .withKeysForEncryption(key) + .build(), + new byte[1] + ).getResult(); + + new AwsCrypto().decryptData(mkp, ciphertext); + } + }); } @Test - public void whenHandlerConfigured_handlerIsInvoked() throws Exception { + void whenHandlerConfigured_handlerIsInvoked() { RequestHandler2 handler = spy(new RequestHandler2() {}); KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -150,7 +155,7 @@ public void whenHandlerConfigured_handlerIsInvoked() throws Exception { } @Test - public void whenShortTimeoutSet_timesOut() throws Exception { + void whenShortTimeoutSet_timesOut() { // By setting a timeout of 1ms, it's not physically possible to complete both the us-west-2 and eu-central-1 // requests due to speed of light limits. KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -179,7 +184,7 @@ public void whenShortTimeoutSet_timesOut() throws Exception { } @Test - public void whenCustomCredentialsSet_theyAreUsed() throws Exception { + void whenCustomCredentialsSet_theyAreUsed() { AWSCredentialsProvider customProvider = spy(new DefaultAWSCredentialsProviderChain()); KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -204,7 +209,7 @@ public void whenCustomCredentialsSet_theyAreUsed() throws Exception { } @Test - public void whenBuilderCloned_credentialsAndConfigurationAreRetained() throws Exception { + void whenBuilderCloned_credentialsAndConfigurationAreRetained() { AWSCredentialsProvider customProvider1 = spy(new DefaultAWSCredentialsProviderChain()); AWSCredentialsProvider customProvider2 = spy(new DefaultAWSCredentialsProviderChain()); @@ -237,7 +242,7 @@ public void whenBuilderCloned_credentialsAndConfigurationAreRetained() throws Ex } @Test - public void whenBuilderCloned_clientBuilderCustomizationIsRetained() throws Exception { + void whenBuilderCloned_clientBuilderCustomizationIsRetained() { RequestHandler2 handler = spy(new RequestHandler2() {}); KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -252,9 +257,9 @@ public void whenBuilderCloned_clientBuilderCustomizationIsRetained() throws Exce verify(handler, atLeastOnce()).beforeRequest(any()); } - @Test(expected = IllegalArgumentException.class) - public void whenBogusEndpointIsSet_constructionFails() throws Exception { - KmsMasterKeyProvider.builder() + @Test + void whenBogusEndpointIsSet_constructionFails() { + assertThrows(IllegalArgumentException.class, () -> KmsMasterKeyProvider.builder() .withClientBuilder( AWSKMSClientBuilder.standard() .withEndpointConfiguration( @@ -262,11 +267,11 @@ public void whenBogusEndpointIsSet_constructionFails() throws Exception { "https://this.does.not.exist.example.com", "bad-region") ) - ); + )); } @Test - public void whenUserAgentsOverridden_originalUAsPreserved() throws Exception { + void whenUserAgentsOverridden_originalUAsPreserved() { RequestHandler2 handler = spy(new RequestHandler2() {}); KmsMasterKeyProvider mkp = KmsMasterKeyProvider.builder() @@ -294,7 +299,7 @@ public void whenUserAgentsOverridden_originalUAsPreserved() throws Exception { } @Test - public void whenDefaultRegionSet_itIsUsedForBareKeyIds() throws Exception { + void whenDefaultRegionSet_itIsUsedForBareKeyIds() { // TODO: Need to set up a role to assume as bare key IDs are relative to the caller account } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/XCompatKmsDecryptTest.java b/src/test/java/com/amazonaws/encryptionsdk/kms/XCompatKmsDecryptTest.java deleted file mode 100644 index f7e7c40f2..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/XCompatKmsDecryptTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2016 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. A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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 com.amazonaws.encryptionsdk.kms; - -import static org.junit.Assert.assertArrayEquals; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import com.amazonaws.encryptionsdk.AwsCrypto; -import com.amazonaws.encryptionsdk.CryptoResult; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -@RunWith(Parameterized.class) -public class XCompatKmsDecryptTest { - private String plaintextFileName; - private String ciphertextFileName; - private String kmsKeyId; - - public XCompatKmsDecryptTest(String plaintextFileName, String ciphertextFileName, String kmsKeyId) { - this.plaintextFileName = plaintextFileName; - this.ciphertextFileName = ciphertextFileName; - this.kmsKeyId = kmsKeyId; - } - - @Parameters(name="{index}: testDecryptFromFile({0}, {1}, {2})") - public static Collection data() throws Exception { - String baseDirName; - baseDirName = System.getProperty("staticCompatibilityResourcesDir"); - if (baseDirName == null) { - baseDirName = - XCompatKmsDecryptTest.class.getProtectionDomain().getCodeSource().getLocation().getPath() + - "aws_encryption_sdk_resources"; - } - - List testCases_ = new ArrayList(); - - String ciphertextManifestName = StringUtils.join( - new String[]{ - baseDirName, - "manifests", - "ciphertext.manifest" - }, - File.separator - ); - File ciphertextManifestFile = new File(ciphertextManifestName); - - if (!ciphertextManifestFile.exists()) { - return Collections.emptyList(); - } - - ObjectMapper ciphertextManifestMapper = new ObjectMapper(); - Map ciphertextManifest = ciphertextManifestMapper.readValue( - ciphertextManifestFile, - new TypeReference>(){} - ); - - List> testCases = (List>)ciphertextManifest.get("test_cases"); - for (Map testCase : testCases) { - Map plaintext = (Map)testCase.get("plaintext"); - Map ciphertext = (Map)testCase.get("ciphertext"); - - List> masterKeys = (List>)testCase.get("master_keys"); - for (Map masterKey : masterKeys) { - String providerId = (String) masterKey.get("provider_id"); - if (providerId.equals("aws-kms") && (boolean)masterKey.get("decryptable")) { - testCases_.add(new Object[] { - baseDirName + File.separator + plaintext.get("filename"), - baseDirName + File.separator + ciphertext.get("filename"), - (String)masterKey.get("key_id") - }); - break; - } - } - } - return testCases_; - } - - @Test - public void testDecryptFromFile() throws Exception { - AwsCrypto crypto = new AwsCrypto(); - final KmsMasterKeyProvider masterKeyProvider = new KmsMasterKeyProvider(kmsKeyId); - byte ciphertextBytes[] = Files.readAllBytes(Paths.get(ciphertextFileName)); - byte plaintextBytes[] = Files.readAllBytes(Paths.get(plaintextFileName)); - final CryptoResult decryptResult = crypto.decryptData( - masterKeyProvider, - ciphertextBytes - ); - assertArrayEquals(plaintextBytes, (byte[])decryptResult.getResult()); - } -} \ No newline at end of file From 9c3e162bf9534128227d49aa82dc53f9e7731abe Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Fri, 7 Feb 2020 11:05:07 -0800 Subject: [PATCH 2/3] Client caching is now enabled by default in AwsKmsClientSupplier --- src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java index 5adbb4f96..e69eb0ff9 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java @@ -65,7 +65,6 @@ class TestVectorRunner { private static final Map cachedData = new HashMap<>(); private static final AwsKmsClientSupplier awsKmsClientSupplier = AwsKmsClientSupplier.builder() .credentialsProvider(new DefaultAWSCredentialsProviderChain()) - .clientCaching(true) .build(); private static final KmsMasterKeyProvider kmsProv = KmsMasterKeyProvider .builder() From 95ae79bd2111fb0f435086e90798c3b0b70f19bb Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Fri, 7 Feb 2020 13:15:38 -0800 Subject: [PATCH 3/3] Rename slow tag to ad_hoc and fix TestVectorRunner --- pom.xml | 6 +++--- src/test/java/com/amazonaws/encryptionsdk/TestUtils.java | 3 ++- .../java/com/amazonaws/encryptionsdk/TestVectorRunner.java | 4 ++-- .../internal/FrameEncryptionHandlerVeryLongTest.java | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 8ed83317f..6722f8e1c 100644 --- a/pom.xml +++ b/pom.xml @@ -197,7 +197,7 @@ - full-test-suite + test-suite true @@ -208,7 +208,7 @@ maven-surefire-plugin 2.22.0 - slow + ad_hoc @@ -226,7 +226,7 @@ maven-surefire-plugin 2.22.0 - slow, integration + ad_hoc, integration true diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java b/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java index 36d616e30..047189918 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestUtils.java @@ -36,8 +36,9 @@ private static byte[] ensureRandomCached(int length) { /** * JUnit tag name marking tests or test classes to be excluded from normal test profiles + * and only run in an ad hoc manner. */ - public static final String TAG_SLOW_TEST = "slow"; + public static final String TAG_AD_HOC = "ad_hoc"; /** * JUnit tag name marking integration tests */ diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java index e69eb0ff9..cfb291b23 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java @@ -144,8 +144,8 @@ private static TestCase parseTest(String testName, Map data, Map JarFile jar) { final String plaintextUrl = (String) data.get("plaintext"); final String ciphertextURL = (String) data.get("ciphertext"); - cachedData.putIfAbsent(plaintextUrl, readBytesFromJar(jar, plaintextUrl)); - cachedData.putIfAbsent(ciphertextURL, readBytesFromJar(jar, ciphertextURL)); + cachedData.computeIfAbsent(plaintextUrl, k -> readBytesFromJar(jar, k)); + cachedData.computeIfAbsent(ciphertextURL, k -> readBytesFromJar(jar, k)); final List keyrings = new ArrayList<>(); final List> mks = new ArrayList<>(); diff --git a/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java b/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java index 8a335d608..7970d441e 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandlerVeryLongTest.java @@ -20,7 +20,7 @@ * This test exhaustively encrypts a 2^32 frame message, which takes approximately 2-3 hours on my hardware. Because of * this long test time, this test is not run as part of the normal suites. */ -@Tag(TestUtils.TAG_SLOW_TEST) +@Tag(TestUtils.TAG_AD_HOC) class FrameEncryptionHandlerVeryLongTest { @Test void exhaustiveIVCheck() throws Exception {