From 5f125d21f54b71246240e10cafe9767714ae364e Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Sun, 1 May 2022 21:18:26 -0700 Subject: [PATCH 1/7] feat(Examples): extendable --- examples/extendable.md | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 examples/extendable.md diff --git a/examples/extendable.md b/examples/extendable.md new file mode 100644 index 00000000..5d447da7 --- /dev/null +++ b/examples/extendable.md @@ -0,0 +1,62 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Required Interface Demonstrations + +## Version + +0.1.0 + +## Implementations + +* [Net](https://github.com/aws/aws-encryption-sdk-dafny/tree/develop/aws-encryption-sdk-net/Examples) + - [Regional Client Supplier](https://github.com/aws/aws-encryption-sdk-dafny/blob/develop/aws-encryption-sdk-net/Examples/ClientSupplier/RegionalRoleClientSupplier.cs) + + + +## Overview + +Every implementation MUST include an example implementation +for every customer extendable class or interface in the Encryption SDK. + +See [example/extendables](./extendables) for specific implementations. + +## Definitions + +### Conventions used in this document + +The key words +"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" +in this document are to be interpreted as described in +[RFC 2119](https://tools.ietf.org/html/rfc2119). + +## Requirements + +- Every example extendable MUST be tested + as part of the continous integration testing. +- Everty example extendable MUST be independent and complete. +- Every example extendable SHOULD follow this layout: + + * In a directory named for the extendable interface/class, + * In a directory named for the example, + * two files should exsist: + * The implementation of the extendable interface/class, + * An example that utilizes it. + +- Every example extendable MUST only contain logic that is reasonable for production use. +- If an example extendable MUST contain logic that is not reasonable for production use, + it MUST include clear comments identifying that logic as such + and instructing the reader what they SHOULD do instead. + +### Example Extendable Templates + +For each extendable, there MUST be directory under [example/extendables](./extendables). +Each example extendable MUST be in the appropriate directory. +Example extendables MUST include sufficent code to clearly demonstrate +how to implement the interface and +how to use the implemented interface. +This code MUST be in the native language. + + + From 6a20fd4e7872987adef0f1b31d1a226657253148 Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Sun, 1 May 2022 22:33:57 -0700 Subject: [PATCH 2/7] feat(Examples): regional role client supplier --- .../regional-role-client-supplier.md | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 examples/extendables/client-supplier/regional-role-client-supplier.md diff --git a/examples/extendables/client-supplier/regional-role-client-supplier.md b/examples/extendables/client-supplier/regional-role-client-supplier.md new file mode 100644 index 00000000..a51d2c5f --- /dev/null +++ b/examples/extendables/client-supplier/regional-role-client-supplier.md @@ -0,0 +1,254 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Regional Role Client Supplier + +Implementations of this MUST follow the rules defined in +[Example Extendables](../../../extendable.md). + +## Implementations + +- [Net](https://github.com/aws/aws-encryption-sdk-dafny/blob/develop/aws-encryption-sdk-net/Examples/ClientSupplier/RegionalRoleClientSupplier.cs) + +## Definitions + +### Conventions used in this document + +The key words +"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" +in this document are to be interpreted as described in +[RFC 2119](https://tools.ietf.org/html/rfc2119). + + +## Regional Role Client Supplier Class + +### Header +```c# +/// +/// Demonstrates implementing a Custom Client Supplier. +/// This Client Supplier will create KMS Clients with different IAM roles, +/// depending on the Region passed. +/// +``` + +### Class + +```c# +// When implementing a Custom Client Supplier ALWAYS extend the Base class, +// not the interface. +public class RegionalRoleClientSupplier : ClientSupplierBase +{ + /// + /// Maps a Region to the Arn of the IAM Role the client supplier will + /// use when supplying a client. + /// + private static Dictionary _regionIAMRoleMap; + + /// + /// Amazon Security Token Service, or STS, allows customers to fetch + /// temporary credentials. + /// + private static IAmazonSecurityTokenService _stsClient; + + public RegionalRoleClientSupplier() + { + _regionIAMRoleMap = GetRegionIAMRoleMap(); + _stsClient = new AmazonSecurityTokenServiceClient(); + } + + /// + /// This is the meat of a Client Supplier. + /// Whenever the AWS Encryption SDK needs to create a KMS client, + /// it will call GetClient for the regions in which it needs to call + /// KMS. + /// In this example, we utilize a Dictionary + /// to map regions to particular IAM Roles. + /// We use Amazon Security Token Service to fetch temporary credentials, + /// and then provision a Key Management Service (KMS) Client + /// with those credentials and the input region. + /// + /// GetClientInput is just the region + /// A KMS Client + /// If the Region requested is missing from the RegionIAMRole Map + /// If the Assume Role call fails + protected override IAmazonKeyManagementService _GetClient(GetClientInput input) + { + // Check our RegionIAMRole map for the provided region. + // If it is missing, throw a Missing Region Exception. + if (!_regionIAMRoleMap.ContainsKey(input.Region)) throw new MissingRegionException(input.Region); + + // Otherwise, call Amazon STS to assume the role. + var iamArn = _regionIAMRoleMap[input.Region]; + var task = _stsClient.AssumeRoleAsync(new AssumeRoleRequest + { + RoleArn = iamArn, + DurationSeconds = 900, // 15 minutes is the minimum value + RoleSessionName = "ESDK-NET-Custom-Client-Example" + }); + AssumeRoleResponse response; + // Await the async response + try + { + response = task.Result; + } + catch (Exception e) + { + throw new AssumeRoleException(input.Region, iamArn, e); + } + + // Return a KMS Client with the credentials from STS and the Region. + return new AmazonKeyManagementServiceClient( + response.Credentials, + RegionEndpoint.GetBySystemName(input.Region)); + } +} +``` + +### Custom Exceptions +These exceptions MUST extend `AwsCryptographicMaterialProvidersBaseException`. + +#### Missing Region Exception +```c# +// Custom Exceptions SHOULD extend from the Library's Base Exception. +// This is a quirk of using Dafny to generate the Encryption SDK. +// The Encryption SDK will handle dotnet's System.Exception, +// but the exception message will be altered. +// By extending from the Library's Base Exception, +// you can ensure the exception's message will be as intended. +public class MissingRegionException : AwsCryptographicMaterialProvidersBaseException +{ + public MissingRegionException(string region) : base( + $"Region {region} is not supported by this client supplier") + { + } +} +``` + +#### Assume Role Exception +```c# +public class AssumeRoleException : AwsCryptographicMaterialProvidersBaseException +{ + public AssumeRoleException(string region, string roleArn, Exception e) : base( + $"Attempt to assume Role Arn {roleArn} for Region {region}" + + $" encountered unexpected: {e.GetType()}: \"{e.Message}\"") + { + // At this time, the Encryption SDK only retains exception messages, + // and not the entire stack trace. + // As such, it is helpful to manually log the exceptions + // (ideally, a logging framework would be used, instead of console). + Console.Out.Write(e); + } +} +``` + +## Client Supplier Example + +Implementations of this example MUST follow the rules defined in +[Example Templates](../../../examples.md#example-templates). + +### Header +```c# +/// Demonstrates using a Custom Client Supplier. +/// See RegionalRoleClientSupplier.cs for the details of implementing a +/// custom client supplier. +/// This example uses an AwsKmsMrkDiscoveryMultiKeyring, but all +/// the AWS Multi Keyrings take Client Suppliers. +``` + +### Summary +```c# +/// Demonstrates using a Custom Client Supplier. +``` + +### Inputs + +- **plaintext** : + Plaintext to encrypt + +- **keyArn** : + KMS Key Arn to encrypt/decrypt data with + +- **accountIds** : + List of trusted AWS Account Ids + +- **regions** : + List of AWS Regions trusted AWS Accounts operate in + +### Steps + +1. Generate or load a ciphertext encrypted by the KMS Key. +```c# +// Instantiate the Material Providers and the AWS Encryption SDK +var materialProviders = + AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); +var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); + +// To focus on Client Suppliers, we will rely on a helper method +// to create the encrypted message (ciphertext). +Dictionary encryptionContext; +MemoryStream ciphertext; +(encryptionContext, ciphertext) = EncryptMessageWithKMSKey( + plaintext, keyArn, materialProviders, encryptionSdk); +``` + +2. Create a KMS Multi Keyring with the `RegionalRoleClientSupplier` +```c# +// Now create a Discovery keyring to use for decryption. +// We are passing in our Custom Client Supplier. +var createDecryptKeyringInput = new CreateAwsKmsMrkDiscoveryMultiKeyringInput +{ + ClientSupplier = new RegionalRoleClientSupplier(), + Regions = regions, + DiscoveryFilter = new DiscoveryFilter() + { + AccountIds = accountIds, + Partition = "aws" + } +}; + +// This is a Multi Keyring composed of MRK Discovery Keyrings. +// All the keyrings have the same Discovery Filter. +// Each keyring has its own KMS Client, which is provisioned by the Custom Client Supplier. +var multiKeyring = materialProviders.CreateAwsKmsMrkDiscoveryMultiKeyring(createDecryptKeyringInput); +``` + +3. Decrypt the ciphertext with created KMS Multi Keyring +```c# +var decryptInput = new DecryptInput +{ + Ciphertext = ciphertext, + Keyring = multiKeyring +}; +var decryptOutput = encryptionSdk.Decrypt(decryptInput); +``` + +4. Verify the encryption context (MAY be done with a helper method) +```c# +VerifyEncryptionContext(decryptOutput, encryptionContext); +``` + +5. Verify the decrypted plaintext is the same as the original (MAY be done with a helper method) +```c# +VerifyDecryptedIsPlaintext(decryptOutput, plaintext); +``` + +6. Test the Missing Region Exception +```c# +// Demonstrate catching a custom exception. +var createMultiFailed = false; +createDecryptKeyringInput.Regions = new List() {RegionEndpoint.CNNorth1.SystemName}; +try { materialProviders.CreateAwsKmsMrkDiscoveryMultiKeyring(createDecryptKeyringInput); } +// Note that the exception returned is NOT a `MissingRegionException` +catch (MissingRegionException) { throw; } +// But is cast down to an `AwsCryptographicMaterialProvidersBaseException`. +catch (AwsCryptographicMaterialProvidersBaseException exception) +{ + // However, the message is as expected. + Assert.Equal( + $"Region {RegionEndpoint.CNNorth1.SystemName} is not supported by this client supplier", + exception.Message); + createMultiFailed = true; +} +finally { Assert.True(createMultiFailed); } +``` From 892a826a566c3f7a188feae2a74b2afafd405783 Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Sun, 1 May 2022 22:48:10 -0700 Subject: [PATCH 3/7] fix(Examples): ran pettier --- examples/extendable.md | 21 +++++++------------ .../regional-role-client-supplier.md | 20 ++++++++++++------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/examples/extendable.md b/examples/extendable.md index 5d447da7..60c63e0a 100644 --- a/examples/extendable.md +++ b/examples/extendable.md @@ -9,10 +9,8 @@ ## Implementations -* [Net](https://github.com/aws/aws-encryption-sdk-dafny/tree/develop/aws-encryption-sdk-net/Examples) +- [Net](https://github.com/aws/aws-encryption-sdk-dafny/tree/develop/aws-encryption-sdk-net/Examples) - [Regional Client Supplier](https://github.com/aws/aws-encryption-sdk-dafny/blob/develop/aws-encryption-sdk-net/Examples/ClientSupplier/RegionalRoleClientSupplier.cs) - - ## Overview @@ -38,13 +36,13 @@ in this document are to be interpreted as described in - Everty example extendable MUST be independent and complete. - Every example extendable SHOULD follow this layout: - * In a directory named for the extendable interface/class, - * In a directory named for the example, - * two files should exsist: - * The implementation of the extendable interface/class, - * An example that utilizes it. + - In a directory named for the extendable interface/class, + - In a directory named for the example, + - two files should exsist: + - The implementation of the extendable interface/class, + - An example that utilizes it. -- Every example extendable MUST only contain logic that is reasonable for production use. +- Every example extendable MUST only contain logic that is reasonable for production use. - If an example extendable MUST contain logic that is not reasonable for production use, it MUST include clear comments identifying that logic as such and instructing the reader what they SHOULD do instead. @@ -54,9 +52,6 @@ in this document are to be interpreted as described in For each extendable, there MUST be directory under [example/extendables](./extendables). Each example extendable MUST be in the appropriate directory. Example extendables MUST include sufficent code to clearly demonstrate -how to implement the interface and +how to implement the interface and how to use the implemented interface. This code MUST be in the native language. - - - diff --git a/examples/extendables/client-supplier/regional-role-client-supplier.md b/examples/extendables/client-supplier/regional-role-client-supplier.md index a51d2c5f..14c99970 100644 --- a/examples/extendables/client-supplier/regional-role-client-supplier.md +++ b/examples/extendables/client-supplier/regional-role-client-supplier.md @@ -3,7 +3,7 @@ # Regional Role Client Supplier -Implementations of this MUST follow the rules defined in +Implementations of this MUST follow the rules defined in [Example Extendables](../../../extendable.md). ## Implementations @@ -20,10 +20,10 @@ The key words in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). - ## Regional Role Client Supplier Class ### Header + ```c# /// /// Demonstrates implementing a Custom Client Supplier. @@ -106,9 +106,11 @@ public class RegionalRoleClientSupplier : ClientSupplierBase ``` ### Custom Exceptions + These exceptions MUST extend `AwsCryptographicMaterialProvidersBaseException`. #### Missing Region Exception + ```c# // Custom Exceptions SHOULD extend from the Library's Base Exception. // This is a quirk of using Dafny to generate the Encryption SDK. @@ -126,6 +128,7 @@ public class MissingRegionException : AwsCryptographicMaterialProvidersBaseExcep ``` #### Assume Role Exception + ```c# public class AssumeRoleException : AwsCryptographicMaterialProvidersBaseException { @@ -148,6 +151,7 @@ Implementations of this example MUST follow the rules defined in [Example Templates](../../../examples.md#example-templates). ### Header + ```c# /// Demonstrates using a Custom Client Supplier. /// See RegionalRoleClientSupplier.cs for the details of implementing a @@ -157,6 +161,7 @@ Implementations of this example MUST follow the rules defined in ``` ### Summary + ```c# /// Demonstrates using a Custom Client Supplier. ``` @@ -165,19 +170,17 @@ Implementations of this example MUST follow the rules defined in - **plaintext** : Plaintext to encrypt - - **keyArn** : KMS Key Arn to encrypt/decrypt data with - - **accountIds** : List of trusted AWS Account Ids - - **regions** : List of AWS Regions trusted AWS Accounts operate in - + ### Steps 1. Generate or load a ciphertext encrypted by the KMS Key. + ```c# // Instantiate the Material Providers and the AWS Encryption SDK var materialProviders = @@ -193,6 +196,7 @@ MemoryStream ciphertext; ``` 2. Create a KMS Multi Keyring with the `RegionalRoleClientSupplier` + ```c# // Now create a Discovery keyring to use for decryption. // We are passing in our Custom Client Supplier. @@ -214,6 +218,7 @@ var multiKeyring = materialProviders.CreateAwsKmsMrkDiscoveryMultiKeyring(create ``` 3. Decrypt the ciphertext with created KMS Multi Keyring + ```c# var decryptInput = new DecryptInput { @@ -224,16 +229,19 @@ var decryptOutput = encryptionSdk.Decrypt(decryptInput); ``` 4. Verify the encryption context (MAY be done with a helper method) + ```c# VerifyEncryptionContext(decryptOutput, encryptionContext); ``` 5. Verify the decrypted plaintext is the same as the original (MAY be done with a helper method) + ```c# VerifyDecryptedIsPlaintext(decryptOutput, plaintext); ``` 6. Test the Missing Region Exception + ```c# // Demonstrate catching a custom exception. var createMultiFailed = false; From 13910f862f46210cba54e9c16d716c64ab15d67f Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Sun, 1 May 2022 22:50:07 -0700 Subject: [PATCH 4/7] fix(Examples): remove native code requirement --- examples/extendable.md | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/extendable.md b/examples/extendable.md index 60c63e0a..e83fcbcf 100644 --- a/examples/extendable.md +++ b/examples/extendable.md @@ -54,4 +54,3 @@ Each example extendable MUST be in the appropriate directory. Example extendables MUST include sufficent code to clearly demonstrate how to implement the interface and how to use the implemented interface. -This code MUST be in the native language. From 2cd6ccc0b17959cc1084d6a6058eed31ffb43297 Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Mon, 2 May 2022 20:07:17 -0700 Subject: [PATCH 5/7] fix(Examples): remove code from client supplier --- .../regional-role-client-supplier.md | 178 ++++-------------- 1 file changed, 40 insertions(+), 138 deletions(-) diff --git a/examples/extendables/client-supplier/regional-role-client-supplier.md b/examples/extendables/client-supplier/regional-role-client-supplier.md index 14c99970..b1e66b41 100644 --- a/examples/extendables/client-supplier/regional-role-client-supplier.md +++ b/examples/extendables/client-supplier/regional-role-client-supplier.md @@ -34,75 +34,38 @@ in this document are to be interpreted as described in ### Class +#### Properties/Fields + +- **RegionIAMRoleMap**: + Maps a Region to the Arn of the + IAM Role the client supplier will + use when supplying a client. + +- **STSClient**: + Amazon Security Token Service, or STS, + allows customers to fetch + temporary credentials. + +#### Methods + +##### GetClient + ```c# -// When implementing a Custom Client Supplier ALWAYS extend the Base class, -// not the interface. -public class RegionalRoleClientSupplier : ClientSupplierBase -{ - /// - /// Maps a Region to the Arn of the IAM Role the client supplier will - /// use when supplying a client. - /// - private static Dictionary _regionIAMRoleMap; - - /// - /// Amazon Security Token Service, or STS, allows customers to fetch - /// temporary credentials. - /// - private static IAmazonSecurityTokenService _stsClient; - - public RegionalRoleClientSupplier() - { - _regionIAMRoleMap = GetRegionIAMRoleMap(); - _stsClient = new AmazonSecurityTokenServiceClient(); - } - - /// - /// This is the meat of a Client Supplier. - /// Whenever the AWS Encryption SDK needs to create a KMS client, - /// it will call GetClient for the regions in which it needs to call - /// KMS. - /// In this example, we utilize a Dictionary - /// to map regions to particular IAM Roles. - /// We use Amazon Security Token Service to fetch temporary credentials, - /// and then provision a Key Management Service (KMS) Client - /// with those credentials and the input region. - /// - /// GetClientInput is just the region - /// A KMS Client - /// If the Region requested is missing from the RegionIAMRole Map - /// If the Assume Role call fails - protected override IAmazonKeyManagementService _GetClient(GetClientInput input) - { - // Check our RegionIAMRole map for the provided region. - // If it is missing, throw a Missing Region Exception. - if (!_regionIAMRoleMap.ContainsKey(input.Region)) throw new MissingRegionException(input.Region); - - // Otherwise, call Amazon STS to assume the role. - var iamArn = _regionIAMRoleMap[input.Region]; - var task = _stsClient.AssumeRoleAsync(new AssumeRoleRequest - { - RoleArn = iamArn, - DurationSeconds = 900, // 15 minutes is the minimum value - RoleSessionName = "ESDK-NET-Custom-Client-Example" - }); - AssumeRoleResponse response; - // Await the async response - try - { - response = task.Result; - } - catch (Exception e) - { - throw new AssumeRoleException(input.Region, iamArn, e); - } - - // Return a KMS Client with the credentials from STS and the Region. - return new AmazonKeyManagementServiceClient( - response.Credentials, - RegionEndpoint.GetBySystemName(input.Region)); - } -} +/// +/// This is the meat of a Client Supplier. +/// Whenever the AWS Encryption SDK needs to create a KMS client, +/// it will call GetClient for the regions +/// in which it needs to call KMS. +/// In this example, we utilize a Dictionary +/// to map regions to particular IAM Roles. +/// We use Amazon Security Token Service to fetch temporary credentials, +/// and then provision a Key Management Service (KMS) Client +/// with those credentials and the input region. +/// +/// GetClientInput is just the region +/// A KMS Client +/// If the Region requested is missing from the RegionIAMRole Map +/// If the Assume Role call fails ``` ### Custom Exceptions @@ -118,31 +81,16 @@ These exceptions MUST extend `AwsCryptographicMaterialProvidersBaseException`. // but the exception message will be altered. // By extending from the Library's Base Exception, // you can ensure the exception's message will be as intended. -public class MissingRegionException : AwsCryptographicMaterialProvidersBaseException -{ - public MissingRegionException(string region) : base( - $"Region {region} is not supported by this client supplier") - { - } -} ``` #### Assume Role Exception ```c# -public class AssumeRoleException : AwsCryptographicMaterialProvidersBaseException -{ - public AssumeRoleException(string region, string roleArn, Exception e) : base( - $"Attempt to assume Role Arn {roleArn} for Region {region}" + - $" encountered unexpected: {e.GetType()}: \"{e.Message}\"") - { - // At this time, the Encryption SDK only retains exception messages, - // and not the entire stack trace. - // As such, it is helpful to manually log the exceptions - // (ideally, a logging framework would be used, instead of console). - Console.Out.Write(e); - } -} +// At this time, the Encryption SDK only retains exception messages, +// and not the entire stack trace. +// As such, it is helpful to manually log the exceptions +// (ideally, a logging framework would be used, instead of console). +Console.Out.Write(e); ``` ## Client Supplier Example @@ -182,17 +130,8 @@ Implementations of this example MUST follow the rules defined in 1. Generate or load a ciphertext encrypted by the KMS Key. ```c# -// Instantiate the Material Providers and the AWS Encryption SDK -var materialProviders = - AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); -var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); - // To focus on Client Suppliers, we will rely on a helper method // to create the encrypted message (ciphertext). -Dictionary encryptionContext; -MemoryStream ciphertext; -(encryptionContext, ciphertext) = EncryptMessageWithKMSKey( - plaintext, keyArn, materialProviders, encryptionSdk); ``` 2. Create a KMS Multi Keyring with the `RegionalRoleClientSupplier` @@ -200,63 +139,26 @@ MemoryStream ciphertext; ```c# // Now create a Discovery keyring to use for decryption. // We are passing in our Custom Client Supplier. -var createDecryptKeyringInput = new CreateAwsKmsMrkDiscoveryMultiKeyringInput -{ - ClientSupplier = new RegionalRoleClientSupplier(), - Regions = regions, - DiscoveryFilter = new DiscoveryFilter() - { - AccountIds = accountIds, - Partition = "aws" - } -}; - // This is a Multi Keyring composed of MRK Discovery Keyrings. // All the keyrings have the same Discovery Filter. -// Each keyring has its own KMS Client, which is provisioned by the Custom Client Supplier. -var multiKeyring = materialProviders.CreateAwsKmsMrkDiscoveryMultiKeyring(createDecryptKeyringInput); +// Each keyring has its own KMS Client, +// which is provisioned by the Custom Client Supplier. ``` 3. Decrypt the ciphertext with created KMS Multi Keyring -```c# -var decryptInput = new DecryptInput -{ - Ciphertext = ciphertext, - Keyring = multiKeyring -}; -var decryptOutput = encryptionSdk.Decrypt(decryptInput); -``` - 4. Verify the encryption context (MAY be done with a helper method) -```c# -VerifyEncryptionContext(decryptOutput, encryptionContext); -``` - 5. Verify the decrypted plaintext is the same as the original (MAY be done with a helper method) -```c# -VerifyDecryptedIsPlaintext(decryptOutput, plaintext); -``` - 6. Test the Missing Region Exception ```c# // Demonstrate catching a custom exception. -var createMultiFailed = false; -createDecryptKeyringInput.Regions = new List() {RegionEndpoint.CNNorth1.SystemName}; -try { materialProviders.CreateAwsKmsMrkDiscoveryMultiKeyring(createDecryptKeyringInput); } +try {...} // Note that the exception returned is NOT a `MissingRegionException` catch (MissingRegionException) { throw; } // But is cast down to an `AwsCryptographicMaterialProvidersBaseException`. catch (AwsCryptographicMaterialProvidersBaseException exception) -{ - // However, the message is as expected. - Assert.Equal( - $"Region {RegionEndpoint.CNNorth1.SystemName} is not supported by this client supplier", - exception.Message); - createMultiFailed = true; -} -finally { Assert.True(createMultiFailed); } +{...} ``` From c91c078ec6825115d6143a46aa445baf37c16f9b Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Tue, 10 May 2022 14:40:52 -0700 Subject: [PATCH 6/7] fix(Example): regional role client supplier --- .../client-supplier/regional-role-client-supplier.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/extendables/client-supplier/regional-role-client-supplier.md b/examples/extendables/client-supplier/regional-role-client-supplier.md index b1e66b41..893a8c3a 100644 --- a/examples/extendables/client-supplier/regional-role-client-supplier.md +++ b/examples/extendables/client-supplier/regional-role-client-supplier.md @@ -37,15 +37,14 @@ in this document are to be interpreted as described in #### Properties/Fields - **RegionIAMRoleMap**: - Maps a Region to the Arn of the + Maps a Region to the Arn of the IAM Role the client supplier will use when supplying a client. - - **STSClient**: - Amazon Security Token Service, or STS, + Amazon Security Token Service, or STS, allows customers to fetch temporary credentials. - + #### Methods ##### GetClient @@ -141,7 +140,7 @@ Implementations of this example MUST follow the rules defined in // We are passing in our Custom Client Supplier. // This is a Multi Keyring composed of MRK Discovery Keyrings. // All the keyrings have the same Discovery Filter. -// Each keyring has its own KMS Client, +// Each keyring has its own KMS Client, // which is provisioned by the Custom Client Supplier. ``` From 206e9ddc554018ccf356b86329fe80d2f19b381b Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Wed, 15 Jun 2022 17:15:11 -0700 Subject: [PATCH 7/7] fix(example): remove comment syntax I left the c# syntax for the exception handling. I want to be specific and clear that the custom exception must be re-raised if caught since that would break our current API. --- examples/extendable.md | 4 +- .../regional-role-client-supplier.md | 100 ++++++++---------- 2 files changed, 47 insertions(+), 57 deletions(-) diff --git a/examples/extendable.md b/examples/extendable.md index e83fcbcf..e8cbb01d 100644 --- a/examples/extendable.md +++ b/examples/extendable.md @@ -39,8 +39,8 @@ in this document are to be interpreted as described in - In a directory named for the extendable interface/class, - In a directory named for the example, - two files should exsist: - - The implementation of the extendable interface/class, - - An example that utilizes it. + - The implementation of the extendable interface/class, + - An example that utilizes it. - Every example extendable MUST only contain logic that is reasonable for production use. - If an example extendable MUST contain logic that is not reasonable for production use, diff --git a/examples/extendables/client-supplier/regional-role-client-supplier.md b/examples/extendables/client-supplier/regional-role-client-supplier.md index 893a8c3a..19959875 100644 --- a/examples/extendables/client-supplier/regional-role-client-supplier.md +++ b/examples/extendables/client-supplier/regional-role-client-supplier.md @@ -24,12 +24,10 @@ in this document are to be interpreted as described in ### Header -```c# -/// -/// Demonstrates implementing a Custom Client Supplier. -/// This Client Supplier will create KMS Clients with different IAM roles, -/// depending on the Region passed. -/// +``` +Demonstrates implementing a Custom Client Supplier. +This Client Supplier will create KMS Clients with different IAM roles, +depending on the Region passed. ``` ### Class @@ -49,22 +47,16 @@ in this document are to be interpreted as described in ##### GetClient -```c# -/// -/// This is the meat of a Client Supplier. -/// Whenever the AWS Encryption SDK needs to create a KMS client, -/// it will call GetClient for the regions -/// in which it needs to call KMS. -/// In this example, we utilize a Dictionary -/// to map regions to particular IAM Roles. -/// We use Amazon Security Token Service to fetch temporary credentials, -/// and then provision a Key Management Service (KMS) Client -/// with those credentials and the input region. -/// -/// GetClientInput is just the region -/// A KMS Client -/// If the Region requested is missing from the RegionIAMRole Map -/// If the Assume Role call fails +``` +This is the meat of a Client Supplier. +Whenever the AWS Encryption SDK needs to create a KMS client, +it will call GetClient for the regions +in which it needs to call KMS. +In this example, we utilize a Dictionary +to map regions to particular IAM Roles. +We use Amazon Security Token Service to fetch temporary credentials, +and then provision a Key Management Service (KMS) Client +with those credentials and the input region. ``` ### Custom Exceptions @@ -73,23 +65,22 @@ These exceptions MUST extend `AwsCryptographicMaterialProvidersBaseException`. #### Missing Region Exception -```c# -// Custom Exceptions SHOULD extend from the Library's Base Exception. -// This is a quirk of using Dafny to generate the Encryption SDK. -// The Encryption SDK will handle dotnet's System.Exception, -// but the exception message will be altered. -// By extending from the Library's Base Exception, -// you can ensure the exception's message will be as intended. +``` +Custom Exceptions SHOULD extend from the Library's Base Exception. +This is a quirk of using Dafny to generate the Encryption SDK. +The Encryption SDK will handle dotnet's System.Exception, +but the exception message will be altered. +By extending from the Library's Base Exception, +you can ensure the exception's message will be as intended. ``` #### Assume Role Exception -```c# -// At this time, the Encryption SDK only retains exception messages, -// and not the entire stack trace. -// As such, it is helpful to manually log the exceptions -// (ideally, a logging framework would be used, instead of console). -Console.Out.Write(e); +``` +At this time, the Encryption SDK only retains exception messages, +and not the entire stack trace. +As such, it is helpful to manually log the exceptions +(ideally, a logging framework would be used, instead of console). ``` ## Client Supplier Example @@ -99,26 +90,24 @@ Implementations of this example MUST follow the rules defined in ### Header -```c# -/// Demonstrates using a Custom Client Supplier. -/// See RegionalRoleClientSupplier.cs for the details of implementing a -/// custom client supplier. -/// This example uses an AwsKmsMrkDiscoveryMultiKeyring, but all -/// the AWS Multi Keyrings take Client Suppliers. +``` +Demonstrates using a Custom Client Supplier. +See RegionalRoleClientSupplier.cs for the details of implementing a +custom client supplier. +This example uses an AwsKmsMrkDiscoveryMultiKeyring, but all +the AWS Multi Keyrings take Client Suppliers. ``` ### Summary -```c# -/// Demonstrates using a Custom Client Supplier. +``` +Demonstrates using a Custom Client Supplier. ``` ### Inputs - **plaintext** : Plaintext to encrypt -- **keyArn** : - KMS Key Arn to encrypt/decrypt data with - **accountIds** : List of trusted AWS Account Ids - **regions** : @@ -128,20 +117,20 @@ Implementations of this example MUST follow the rules defined in 1. Generate or load a ciphertext encrypted by the KMS Key. -```c# -// To focus on Client Suppliers, we will rely on a helper method -// to create the encrypted message (ciphertext). +``` +To focus on Client Suppliers, we will rely on a helper method +to create the encrypted message (ciphertext). ``` 2. Create a KMS Multi Keyring with the `RegionalRoleClientSupplier` -```c# -// Now create a Discovery keyring to use for decryption. -// We are passing in our Custom Client Supplier. -// This is a Multi Keyring composed of MRK Discovery Keyrings. -// All the keyrings have the same Discovery Filter. -// Each keyring has its own KMS Client, -// which is provisioned by the Custom Client Supplier. +``` +Now create a Discovery keyring to use for decryption. +We are passing in our Custom Client Supplier. +This is a Multi Keyring composed of MRK Discovery Keyrings. +All the keyrings have the same Discovery Filter. +Each keyring has its own KMS Client, +which is provisioned by the Custom Client Supplier. ``` 3. Decrypt the ciphertext with created KMS Multi Keyring @@ -160,4 +149,5 @@ catch (MissingRegionException) { throw; } // But is cast down to an `AwsCryptographicMaterialProvidersBaseException`. catch (AwsCryptographicMaterialProvidersBaseException exception) {...} +// However, the message is as expected. ```