From cae7696c6b2c4cc981fcd3c0f367f8466bfaf604 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 3 Oct 2024 16:28:05 -0700 Subject: [PATCH] test(test_vectors): Support reading manifests that specify a hierarchy keyring (#649) --- .github/workflows/library_interop_tests.yml | 17 ++++++ .github/workflows/library_net_tests.yml | 9 +++ .../AWSEncryptionSDKTestVectorLib.csproj | 3 + .../TestVectorLib/MaterialProviderFactory.cs | 58 ++++++++++++++++++- .../TestVectorLib/TestVectorTypes.cs | 6 ++ 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/.github/workflows/library_interop_tests.yml b/.github/workflows/library_interop_tests.yml index b67887fed..112b6825a 100644 --- a/.github/workflows/library_interop_tests.yml +++ b/.github/workflows/library_interop_tests.yml @@ -76,6 +76,14 @@ jobs: # This works because `node` is installed by default on GHA runners CORES=$(node -e 'console.log(os.cpus().length)') make transpile_net CORES=$CORES + + - name: Compile MPL TestVectors implementation + shell: bash + working-directory: ./mpl/TestVectorsAwsCryptographicMaterialProviders + run: | + # This works because `node` is installed by default on GHA runners + CORES=$(node -e 'console.log(os.cpus().length)') + make transpile_net CORES=$CORES - name: Fetch Python 2.3.0 Test Vectors working-directory: ./ @@ -166,6 +174,15 @@ jobs: # This works because `node` is installed by default on GHA runners CORES=$(node -e 'console.log(os.cpus().length)') make transpile_net CORES=$CORES + + + - name: Compile MPL TestVectors implementation + shell: bash + working-directory: ./mpl/TestVectorsAwsCryptographicMaterialProviders + run: | + # This works because `node` is installed by default on GHA runners + CORES=$(node -e 'console.log(os.cpus().length)') + make transpile_net CORES=$CORES # # TODO: Fix Zip file creation on Windows diff --git a/.github/workflows/library_net_tests.yml b/.github/workflows/library_net_tests.yml index 4ab2e274b..910f5200f 100644 --- a/.github/workflows/library_net_tests.yml +++ b/.github/workflows/library_net_tests.yml @@ -92,6 +92,15 @@ jobs: CORES=$(node -e 'console.log(os.cpus().length)') make transpile_net CORES=$CORES + + - name: Compile MPL TestVectors implementation + shell: bash + working-directory: ./mpl/TestVectorsAwsCryptographicMaterialProviders + run: | + # This works because `node` is installed by default on GHA runners + CORES=$(node -e 'console.log(os.cpus().length)') + make transpile_net CORES=$CORES + - name: Test .NET Framework net48 working-directory: ./AwsEncryptionSDK if: matrix.os == 'windows-latest' diff --git a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/AWSEncryptionSDKTestVectorLib.csproj b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/AWSEncryptionSDKTestVectorLib.csproj index 6c283d130..5fd06ea5d 100644 --- a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/AWSEncryptionSDKTestVectorLib.csproj +++ b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/AWSEncryptionSDKTestVectorLib.csproj @@ -10,6 +10,9 @@ + + + diff --git a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/MaterialProviderFactory.cs b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/MaterialProviderFactory.cs index 327648c55..14016c03b 100644 --- a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/MaterialProviderFactory.cs +++ b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/MaterialProviderFactory.cs @@ -2,9 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics; +using Newtonsoft.Json; using Amazon; +using Amazon.DynamoDBv2; using Amazon.KeyManagementService; +using AWS.Cryptography.KeyStore; using AWS.Cryptography.MaterialProviders; +using AWS.Cryptography.MaterialProvidersTestVectorKeys; using RSAEncryption; @@ -18,6 +22,7 @@ public enum CryptoOperation public static class MaterialProviderFactory { private static readonly MaterialProviders materialProviders = new(new MaterialProvidersConfig()); + private static KeyVectors singletonKeyVectors; public static ICryptographicMaterialsManager CreateDecryptCmm( DecryptVector vector, @@ -160,6 +165,57 @@ private static IKeyring CreateKeyring(MasterKey keyInfo, Key key, CryptoOperatio return materialProviders.CreateAwsKmsMrkDiscoveryKeyring(createKeyringInput); } + if (keyInfo.Type == "aws-kms-hierarchy") { + // Lazily create a singleton KeyVectors client. + // A KeyVectors manifest is only required if a test vector specifies a hierarchy keyring. + // This specification can only be determined at runtime while reading the test vector manifest. + if (singletonKeyVectors == null) { + string manifestPath; + try + { + manifestPath = Utils.GetEnvironmentVariableOrError("DAFNY_AWS_ESDK_TEST_VECTOR_MANIFEST_PATH"); + } + catch (ArgumentException e) + { + throw new ArgumentException("Hierarchy keyring test vectors must supply a KeyVectors manifest", e); + } + DecryptManifest manifest = Utils.LoadObjectFromPath(manifestPath); + KeyVectorsConfig keyVectorsConfig = new KeyVectorsConfig + { + KeyManifestPath = Utils.ManifestUriToPath(manifest.KeysUri, manifestPath) + }; + singletonKeyVectors = new(keyVectorsConfig); + } + + // Convert JSON to bytes for KeyVectors input + string jsonString = JsonConvert.SerializeObject(keyInfo); + + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(jsonString); + writer.Flush(); + stream.Position = 0; + + // Create KeyVectors keyring + var getKeyDescriptionInput = new GetKeyDescriptionInput + { + Json = stream + }; + + var desc = singletonKeyVectors.GetKeyDescription(getKeyDescriptionInput); + + var testVectorKeyringInput = new TestVectorKeyringInput + { + KeyDescription = desc.KeyDescription + }; + + var keyring = singletonKeyVectors.CreateTestVectorKeyring( + testVectorKeyringInput + ); + + return keyring!; + } + if (keyInfo.Type == "raw" && keyInfo.EncryptionAlgorithm == "aes") { CreateRawAesKeyringInput createKeyringInput = new CreateRawAesKeyringInput { @@ -209,7 +265,7 @@ private static IKeyring CreateKeyring(MasterKey keyInfo, Key key, CryptoOperatio // string operationStr = operation == CryptoOperation.ENCRYPT // ? "encryption" // : "decryption"; - throw new Exception($"Unsupported keyring type for {operation}"); + throw new Exception($"Unsupported keyring {keyInfo.Type} type for {operation}"); } private static AesWrappingAlg AesAlgorithmFromBits(ushort bits) { diff --git a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/TestVectorTypes.cs b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/TestVectorTypes.cs index a3e6dcf35..8dcc71151 100644 --- a/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/TestVectorTypes.cs +++ b/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/TestVectorTypes.cs @@ -25,6 +25,12 @@ public class Key { public string? Encoding { get; set; } [JsonProperty("material")] public string? Material { get; set; } + [JsonProperty("branchKeyVersion")] + public string? BranchKeyVersion { get; set; } + [JsonProperty("branchKey")] + public string? BranchKey { get; set; } + [JsonProperty("beaconKey")] + public string? BeaconKey { get; set; } } public class KeyManifest