From f0951f7c3ab9ff4a1d3b406fbbd2db94a8ac0794 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Mon, 6 Apr 2020 19:06:47 -0700 Subject: [PATCH 01/10] docs: add CMM examples --- .../src/crypto_materials_manager/__init__.py | 7 + .../caching/__init__.py | 7 + .../caching/simple_cache.py | 94 ++++++++++++ .../custom_cmm/__init__.py | 10 ++ .../custom_cmm/algorithm_suite_enforcement.py | 119 +++++++++++++++ .../requiring_encryption_context_fields.py | 144 ++++++++++++++++++ .../explicit_default.py | 73 +++++++++ 7 files changed, 454 insertions(+) create mode 100644 examples/src/crypto_materials_manager/__init__.py create mode 100644 examples/src/crypto_materials_manager/caching/__init__.py create mode 100644 examples/src/crypto_materials_manager/caching/simple_cache.py create mode 100644 examples/src/crypto_materials_manager/custom_cmm/__init__.py create mode 100644 examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py create mode 100644 examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py create mode 100644 examples/src/crypto_materials_manager/explicit_default.py diff --git a/examples/src/crypto_materials_manager/__init__.py b/examples/src/crypto_materials_manager/__init__.py new file mode 100644 index 000000000..f413e63bd --- /dev/null +++ b/examples/src/crypto_materials_manager/__init__.py @@ -0,0 +1,7 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Cryptographic materials manager examples. + +These examples show how to create and use cryptographic materials managers. +""" diff --git a/examples/src/crypto_materials_manager/caching/__init__.py b/examples/src/crypto_materials_manager/caching/__init__.py new file mode 100644 index 000000000..2c55faad8 --- /dev/null +++ b/examples/src/crypto_materials_manager/caching/__init__.py @@ -0,0 +1,7 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Caching cryptographic materials manager examples. + +These examples show how to configure and use the caching cryptographic materials manager. +""" diff --git a/examples/src/crypto_materials_manager/caching/simple_cache.py b/examples/src/crypto_materials_manager/caching/simple_cache.py new file mode 100644 index 000000000..3380404c2 --- /dev/null +++ b/examples/src/crypto_materials_manager/caching/simple_cache.py @@ -0,0 +1,94 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +The default cryptographic materials manager (CMM) +creates new encryption and decryption materials +on every call. +This means every encrypted message is protected by a unique data key, +but it also means that you need to interact with your key management system +in order to process any message. +If this causes performance, operations, or cost issues for you, +you might benefit from data key caching. + +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html + +This examples shows how to configure the caching CMM +to reuse data keys across multiple encrypted messages. + +In this example, we use an AWS KMS customer master key (CMK), +but you can use other key management options with the AWS Encryption SDK. +For examples that demonstrate how to use other key management configurations, +see the ``keyring`` and ``master_key_provider`` directories. + +In this example, we use the one-step encrypt and decrypt APIs. +""" +import aws_encryption_sdk +from aws_encryption_sdk.caches.local import LocalCryptoMaterialsCache +from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring +from aws_encryption_sdk.materials_managers.caching import CachingCryptoMaterialsManager + + +def run(aws_kms_cmk, source_plaintext): + # type: (str, bytes) -> None + """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + + :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys + :param bytes source_plaintext: Plaintext to encrypt + """ + # Prepare your encryption context. + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # Create the keyring that determines how your data keys are protected. + keyring = KmsKeyring(generator_key_id=aws_kms_cmk) + + # Create the caching cryptographic materials manager using your keyring. + cmm = CachingCryptoMaterialsManager( + keyring=keyring, + # The cache is where the caching CMM stores the materials. + # + # LocalCryptoMaterialsCache gives you a local, in-memory, cache. + cache=LocalCryptoMaterialsCache(capacity=100), + # max_age determines how long the caching CMM will reuse materials. + # + # This example uses two minutes. + # In production, always choose as small a value as possible + # that works for your requirements. + max_age=120.0, + # max_messages_encrypted determines how many messages + # the caching CMM will protect with the same materials. + # + # In production, always choose as small a value as possible + # that works for your requirements. + max_messages_encrypted=10, + ) + + # Encrypt your plaintext data. + ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( + source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm + ) + + # Demonstrate that the ciphertext and plaintext are different. + assert ciphertext != source_plaintext + + # Decrypt your encrypted data using the same cryptographic materials manager you used on encrypt. + # + # You do not need to specify the encryption context on decrypt + # because the header of the encrypted message includes the encryption context. + decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=cmm) + + # Demonstrate that the decrypted plaintext is identical to the original plaintext. + assert decrypted == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes + # the encryption context that you specified when encrypting. + # The AWS Encryption SDK can add pairs, so don't require an exact match. + # + # In production, always use a meaningful encryption context. + assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) diff --git a/examples/src/crypto_materials_manager/custom_cmm/__init__.py b/examples/src/crypto_materials_manager/custom_cmm/__init__.py new file mode 100644 index 000000000..98bb2d682 --- /dev/null +++ b/examples/src/crypto_materials_manager/custom_cmm/__init__.py @@ -0,0 +1,10 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Cuystom cryptographic materials manager (CMM) examples. + +The AWS Encryption SDK includes CMMs for common use cases, +but you might need to do something else. + +These examples show how you could create your own CMM for some specific requirements. +""" diff --git a/examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py new file mode 100644 index 000000000..9818995c5 --- /dev/null +++ b/examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py @@ -0,0 +1,119 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +The AWS Encryption SDK supports several different algorithm suites +that offer different security properties. + +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/supported-algorithms.html + +By default, the AWS Encryption SDK will let you use any of these, +but you might want to restrict that further. +We do not recommend using the algorithm suites without key derivation, +so for this example we will show how to make a custom CMM +that will not allow you to use those algorithm suites. +""" +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import AlgorithmSuite, KDFSuite +from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring +from aws_encryption_sdk.keyrings.base import Keyring +from aws_encryption_sdk.materials_managers import ( + DecryptionMaterials, + DecryptionMaterialsRequest, + EncryptionMaterials, + EncryptionMaterialsRequest, +) +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager +from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager + + +class UnsupportedAlgorithmSuite(Exception): + """Indicate that an unsupported algorithm suite was requested.""" + + +class OnlyKdfAlgorithmSuitesCryptoMaterialsManager(CryptoMaterialsManager): + """Only allow encryption requests for algorithm suites with a KDF.""" + + def __init__(self, keyring): + # type: (Keyring) -> None + """Set up the inner cryptographic materials manager using the provided keyring. + + :param Keyring keyring: Keyring to use in the inner cryptographic materials manager + """ + self._cmm = DefaultCryptoMaterialsManager(keyring=keyring) + + def get_encryption_materials(self, request): + # type: (EncryptionMaterialsRequest) -> EncryptionMaterials + """Block any requests that include an algorithm suite without a KDF.""" + if request.algorithm is not None and request.algorithm.kdf is KDFSuite.NONE: + raise UnsupportedAlgorithmSuite("Non-KDF algorithm suites are not allowed!") + + return self._cmm.get_encryption_materials(request) + + def decrypt_materials(self, request): + # type: (DecryptionMaterialsRequest) -> DecryptionMaterials + """Be more permissive on decrypt and just pass through.""" + return self._cmm.decrypt_materials(request) + + +def run(aws_kms_cmk, source_plaintext): + # type: (str, bytes) -> None + """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + + :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys + :param bytes source_plaintext: Plaintext to encrypt + """ + # Prepare your encryption context. + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # Create the keyring that determines how your data keys are protected. + keyring = KmsKeyring(generator_key_id=aws_kms_cmk) + + # Create the filtering cryptographic materials manager using your keyring. + cmm = OnlyKdfAlgorithmSuitesCryptoMaterialsManager(keyring=keyring) + + # Demonstrate that the filtering CMM will not let you use non-KDF algorithm suites. + try: + aws_encryption_sdk.encrypt( + source=source_plaintext, + encryption_context=encryption_context, + materials_manager=cmm, + algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16, + ) + except UnsupportedAlgorithmSuite: + # You asked for a non-KDF algorithm suite. + # Reaching this point means everything is working as expected. + pass + else: + # The filtering CMM keeps this from happening. + raise AssertionError("The filtering CMM does not let this happen!") + + # Encrypt your plaintext data. + ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( + source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm + ) + + # Demonstrate that the ciphertext and plaintext are different. + assert ciphertext != source_plaintext + + # Decrypt your encrypted data using the same cryptographic materials manager you used on encrypt. + # + # You do not need to specify the encryption context on decrypt + # because the header of the encrypted message includes the encryption context. + decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=cmm) + + # Demonstrate that the decrypted plaintext is identical to the original plaintext. + assert decrypted == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes + # the encryption context that you specified when encrypting. + # The AWS Encryption SDK can add pairs, so don't require an exact match. + # + # In production, always use a meaningful encryption context. + assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) diff --git a/examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py new file mode 100644 index 000000000..01c0c5e23 --- /dev/null +++ b/examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py @@ -0,0 +1,144 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Encryption context is a powerful tool for access and audit controls +because it lets you tie *non-secret* metadata about a plaintext value to the encrypted message. +This is especially powerful when you use the AWS Encryption SDK with AWS KMS, +but within the context of the AWS Encryption SDK alone +you can use cryptographic materials managers to analyse the encryption context +to provide logical controls and additional metadata. + +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context +https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context + +This example shows how to create a custom cryptographic materials manager (CMM) +that requires a particular field in any encryption context. +""" +import aws_encryption_sdk +from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring +from aws_encryption_sdk.keyrings.base import Keyring +from aws_encryption_sdk.materials_managers import ( + DecryptionMaterials, + DecryptionMaterialsRequest, + EncryptionMaterials, + EncryptionMaterialsRequest, +) +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager +from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager + + +class MissingClassificationError(Exception): + """Indicates that an encryption context was found that lacked a classification identifier.""" + + +class ClassificationRequiringCryptoMaterialsManager(CryptoMaterialsManager): + """Only allow requests when the encryption context contains a classification identifier.""" + + def __init__(self, keyring): + # type: (Keyring) -> None + """Set up the inner cryptographic materials manager using the provided keyring. + + :param Keyring keyring: Keyring to use in the inner cryptographic materials manager + """ + self._classification_field = "classification" + self._classification_error = MissingClassificationError("Encryption context does not contain classification!") + self._cmm = DefaultCryptoMaterialsManager(keyring=keyring) + + def get_encryption_materials(self, request): + # type: (EncryptionMaterialsRequest) -> EncryptionMaterials + """Block any requests that do not contain a classification identifier in the encryption context.""" + if self._classification_field not in request.encryption_context: + raise self._classification_error + + return self._cmm.get_encryption_materials(request) + + def decrypt_materials(self, request): + # type: (DecryptionMaterialsRequest) -> DecryptionMaterials + """Block any requests that do not contain a classification identifier in the encryption context.""" + if self._classification_field not in request.encryption_context: + raise self._classification_error + + return self._cmm.decrypt_materials(request) + + +def run(aws_kms_cmk, source_plaintext): + # type: (str, bytes) -> None + """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + + :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys + :param bytes source_plaintext: Plaintext to encrypt + """ + # Prepare your encryption context. + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # Create the keyring that determines how your data keys are protected. + keyring = KmsKeyring(generator_key_id=aws_kms_cmk) + + # Create the filtering cryptographic materials manager using your keyring. + cmm = ClassificationRequiringCryptoMaterialsManager(keyring=keyring) + + # Demonstrate that the filtering CMM will not let you encrypt without a classification identifier. + try: + aws_encryption_sdk.encrypt( + source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm, + ) + except MissingClassificationError: + # Your encryption context did not contain a classification identifier. + # Reaching this point means everything is working as expected. + pass + else: + # The filtering CMM keeps this from happening. + raise AssertionError("The filtering CMM does not let this happen!") + + # Encrypt your plaintext data. + classified_ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( + source=source_plaintext, + encryption_context=dict(classification="secret", **encryption_context), + materials_manager=cmm, + ) + + # Demonstrate that the ciphertext and plaintext are different. + assert classified_ciphertext != source_plaintext + + # Decrypt your encrypted data using the same cryptographic materials manager you used on encrypt. + # + # You do not need to specify the encryption context on decrypt + # because the header of the encrypted message includes the encryption context. + decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=classified_ciphertext, materials_manager=cmm) + + # Demonstrate that the decrypted plaintext is identical to the original plaintext. + assert decrypted == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes + # the encryption context that you specified when encrypting. + # The AWS Encryption SDK can add pairs, so don't require an exact match. + # + # In production, always use a meaningful encryption context. + assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) + + # Now demonstrate the decrypt path of the filtering cryptographic materials manager. + + # Encrypt your plaintext using the keyring and do not include a classification identifier. + unclassified_ciphertext, encrypt_header = aws_encryption_sdk.encrypt( + source=source_plaintext, encryption_context=encryption_context, keyring=keyring + ) + + assert "classification" not in encrypt_header.encryption_context + + # Demonstrate that the filtering CMM will not let you decrypt messages without classification identifiers. + try: + aws_encryption_sdk.decrypt(source=unclassified_ciphertext, materials_manager=cmm) + except MissingClassificationError: + # Your encryption context did not contain a classification identifier. + # Reaching this point means everything is working as expected. + pass + else: + # The filtering CMM keeps this from happening. + raise AssertionError("The filtering CMM does not let this happen!") diff --git a/examples/src/crypto_materials_manager/explicit_default.py b/examples/src/crypto_materials_manager/explicit_default.py new file mode 100644 index 000000000..803aab75b --- /dev/null +++ b/examples/src/crypto_materials_manager/explicit_default.py @@ -0,0 +1,73 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +The default cryptographic materials manager (CMM) +is a CMM that uses a keyring or master key provider +to manage the data key materials. +When using the encrypt and decrypt APIs, as well as the caching CMM, +you can supply either a CMM, a keyring, or a master key provider. +If you supply a keyring or master key provider +those components will automatically wrap it in a default CMM. + +This example shows how you could do this manually if you wanted to. + +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager + +In this example, we use an AWS KMS customer master key (CMK), +but you can use other key management options with the AWS Encryption SDK. +For examples that demonstrate how to use other key management configurations, +see the ``keyring`` and ``master_key_provider`` directories. + +In this example, we use the one-step encrypt and decrypt APIs. +""" +import aws_encryption_sdk +from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring +from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager + + +def run(aws_kms_cmk, source_plaintext): + # type: (str, bytes) -> None + """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + + :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys + :param bytes source_plaintext: Plaintext to encrypt + """ + # Prepare your encryption context. + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # Create the keyring that determines how your data keys are protected. + keyring = KmsKeyring(generator_key_id=aws_kms_cmk) + + # Wrap that keyring in a default cryptographic materials manager. + cmm = DefaultCryptoMaterialsManager(keyring=keyring) + + # Encrypt your plaintext data. + ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( + source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm + ) + + # Demonstrate that the ciphertext and plaintext are different. + assert ciphertext != source_plaintext + + # Decrypt your encrypted data using the same cryptographic materials manager you used on encrypt. + # + # You do not need to specify the encryption context on decrypt + # because the header of the encrypted message includes the encryption context. + decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=cmm) + + # Demonstrate that the decrypted plaintext is identical to the original plaintext. + assert decrypted == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes + # the encryption context that you specified when encrypting. + # The AWS Encryption SDK can add pairs, so don't require an exact match. + # + # In production, always use a meaningful encryption context. + assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) From be23069b0961f344a333d79680269880e25d6ec3 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Mon, 6 Apr 2020 19:45:52 -0700 Subject: [PATCH 02/10] docs: add CMM examples to readme --- examples/README.md | 7 +++++++ .../{custom_cmm => custom}/__init__.py | 0 .../{custom_cmm => custom}/algorithm_suite_enforcement.py | 0 .../requiring_encryption_context_fields.py | 0 examples/src/crypto_materials_manager/explicit_default.py | 3 +++ 5 files changed, 10 insertions(+) rename examples/src/crypto_materials_manager/{custom_cmm => custom}/__init__.py (100%) rename examples/src/crypto_materials_manager/{custom_cmm => custom}/algorithm_suite_enforcement.py (100%) rename examples/src/crypto_materials_manager/{custom_cmm => custom}/requiring_encryption_context_fields.py (100%) diff --git a/examples/README.md b/examples/README.md index c4c0e67ec..355265b3b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -59,6 +59,13 @@ We start with AWS KMS examples, then show how to use other wrapping keys. * How to combine AWS KMS with an offline escrow key * [with keyrings](./src/keyring/multi/aws_kms_with_escrow.py) * [with master key providers](./src/master_key_provider/multi/aws_kms_with_escrow.py) +* How to reuse data keys across multiple messages + * [with the caching cryptographic materials manager](./src/crypto_materials_manager/caching/simple_cache.py) +* How to restrict algorithm suites + * [with a custom cryptographic materials manager](src/crypto_materials_manager/custom/algorithm_suite_enforcement.py) +* How to require encryption context fields + * [with a custom cryptographic materials manager](src/crypto_materials_manager/custom/requiring_encryption_context_fields.py) +* [How to explicitly use the default cryptographic materials manager](./src/crypto_materials_manager/explicit_default.py) ### Keyrings diff --git a/examples/src/crypto_materials_manager/custom_cmm/__init__.py b/examples/src/crypto_materials_manager/custom/__init__.py similarity index 100% rename from examples/src/crypto_materials_manager/custom_cmm/__init__.py rename to examples/src/crypto_materials_manager/custom/__init__.py diff --git a/examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py similarity index 100% rename from examples/src/crypto_materials_manager/custom_cmm/algorithm_suite_enforcement.py rename to examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py diff --git a/examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py similarity index 100% rename from examples/src/crypto_materials_manager/custom_cmm/requiring_encryption_context_fields.py rename to examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py diff --git a/examples/src/crypto_materials_manager/explicit_default.py b/examples/src/crypto_materials_manager/explicit_default.py index 803aab75b..824d8a076 100644 --- a/examples/src/crypto_materials_manager/explicit_default.py +++ b/examples/src/crypto_materials_manager/explicit_default.py @@ -10,6 +10,9 @@ those components will automatically wrap it in a default CMM. This example shows how you could do this manually if you wanted to. +This can be useful when constructing custom CMMs. +For examples showing how to create custom CMMs, +see the ``crypto_materials_manager/custom`` directory. https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager From 1d07025a311f960bc4faf1418883aca765edd676 Mon Sep 17 00:00:00 2001 From: Matt Bullock Date: Thu, 9 Apr 2020 12:27:55 -0700 Subject: [PATCH 03/10] docs: apply suggestions from code review Co-Authored-By: Wesley Rosenblum <55108558+WesleyRosenblum@users.noreply.github.com> --- examples/src/crypto_materials_manager/caching/simple_cache.py | 2 +- examples/src/crypto_materials_manager/custom/__init__.py | 2 +- .../custom/requiring_encryption_context_fields.py | 2 +- examples/src/crypto_materials_manager/explicit_default.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/src/crypto_materials_manager/caching/simple_cache.py b/examples/src/crypto_materials_manager/caching/simple_cache.py index 3380404c2..89e7c0390 100644 --- a/examples/src/crypto_materials_manager/caching/simple_cache.py +++ b/examples/src/crypto_materials_manager/caching/simple_cache.py @@ -12,7 +12,7 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html -This examples shows how to configure the caching CMM +This example shows how to configure the caching CMM to reuse data keys across multiple encrypted messages. In this example, we use an AWS KMS customer master key (CMK), diff --git a/examples/src/crypto_materials_manager/custom/__init__.py b/examples/src/crypto_materials_manager/custom/__init__.py index 98bb2d682..202647480 100644 --- a/examples/src/crypto_materials_manager/custom/__init__.py +++ b/examples/src/crypto_materials_manager/custom/__init__.py @@ -1,7 +1,7 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """ -Cuystom cryptographic materials manager (CMM) examples. +Custom cryptographic materials manager (CMM) examples. The AWS Encryption SDK includes CMMs for common use cases, but you might need to do something else. diff --git a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py index 01c0c5e23..6e91eb8e8 100644 --- a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py +++ b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py @@ -12,7 +12,7 @@ https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context This example shows how to create a custom cryptographic materials manager (CMM) -that requires a particular field in any encryption context. +that requires a particular field in the encryption context. """ import aws_encryption_sdk from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring diff --git a/examples/src/crypto_materials_manager/explicit_default.py b/examples/src/crypto_materials_manager/explicit_default.py index 824d8a076..a6bb5c985 100644 --- a/examples/src/crypto_materials_manager/explicit_default.py +++ b/examples/src/crypto_materials_manager/explicit_default.py @@ -48,7 +48,7 @@ def run(aws_kms_cmk, source_plaintext): # Create the keyring that determines how your data keys are protected. keyring = KmsKeyring(generator_key_id=aws_kms_cmk) - # Wrap that keyring in a default cryptographic materials manager. + # Wrap that keyring in the default cryptographic materials manager. cmm = DefaultCryptoMaterialsManager(keyring=keyring) # Encrypt your plaintext data. From 82333bd320185c96bb305cfdcbf546f7f91caf5f Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 12:39:48 -0700 Subject: [PATCH 04/10] docs: fix and refine examples docs --- .../src/crypto_materials_manager/caching/simple_cache.py | 2 +- .../custom/algorithm_suite_enforcement.py | 6 +++++- .../custom/requiring_encryption_context_fields.py | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/src/crypto_materials_manager/caching/simple_cache.py b/examples/src/crypto_materials_manager/caching/simple_cache.py index 89e7c0390..bb14b25fe 100644 --- a/examples/src/crypto_materials_manager/caching/simple_cache.py +++ b/examples/src/crypto_materials_manager/caching/simple_cache.py @@ -30,7 +30,7 @@ def run(aws_kms_cmk, source_plaintext): # type: (str, bytes) -> None - """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + """Demonstrate an encrypt/decrypt cycle using the caching cryptographic materials manager. :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys :param bytes source_plaintext: Plaintext to encrypt diff --git a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py index 9818995c5..902cd7bb8 100644 --- a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py +++ b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py @@ -39,6 +39,10 @@ def __init__(self, keyring): :param Keyring keyring: Keyring to use in the inner cryptographic materials manager """ + # Wrap the provided keyring in the default cryptographic materials manager (CMM). + # + # This is the same thing that the encrypt and decrypt APIs, as well as the caching CMM, + # do if you provide a keyring instead of a CMM. self._cmm = DefaultCryptoMaterialsManager(keyring=keyring) def get_encryption_materials(self, request): @@ -57,7 +61,7 @@ def decrypt_materials(self, request): def run(aws_kms_cmk, source_plaintext): # type: (str, bytes) -> None - """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + """Demonstrate an encrypt/decrypt cycle using a custom cryptographic materials manager that filters requests. :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys :param bytes source_plaintext: Plaintext to encrypt diff --git a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py index 6e91eb8e8..d84240fa0 100644 --- a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py +++ b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py @@ -42,6 +42,10 @@ def __init__(self, keyring): """ self._classification_field = "classification" self._classification_error = MissingClassificationError("Encryption context does not contain classification!") + # Wrap the provided keyring in the default cryptographic materials manager (CMM). + # + # This is the same thing that the encrypt and decrypt APIs, as well as the caching CMM, + # do if you provide a keyring instead of a CMM. self._cmm = DefaultCryptoMaterialsManager(keyring=keyring) def get_encryption_materials(self, request): @@ -63,7 +67,7 @@ def decrypt_materials(self, request): def run(aws_kms_cmk, source_plaintext): # type: (str, bytes) -> None - """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. + """Demonstrate an encrypt/decrypt cycle using a custom cryptographic materials manager that filters requests. :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys :param bytes source_plaintext: Plaintext to encrypt From 1f6f7a08cfb84f6d686871c27679ec3dae6aa18a Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 12:40:38 -0700 Subject: [PATCH 05/10] chore: remove redundant example --- examples/README.md | 1 - .../explicit_default.py | 76 ------------------- 2 files changed, 77 deletions(-) delete mode 100644 examples/src/crypto_materials_manager/explicit_default.py diff --git a/examples/README.md b/examples/README.md index 355265b3b..081e62fab 100644 --- a/examples/README.md +++ b/examples/README.md @@ -65,7 +65,6 @@ We start with AWS KMS examples, then show how to use other wrapping keys. * [with a custom cryptographic materials manager](src/crypto_materials_manager/custom/algorithm_suite_enforcement.py) * How to require encryption context fields * [with a custom cryptographic materials manager](src/crypto_materials_manager/custom/requiring_encryption_context_fields.py) -* [How to explicitly use the default cryptographic materials manager](./src/crypto_materials_manager/explicit_default.py) ### Keyrings diff --git a/examples/src/crypto_materials_manager/explicit_default.py b/examples/src/crypto_materials_manager/explicit_default.py deleted file mode 100644 index a6bb5c985..000000000 --- a/examples/src/crypto_materials_manager/explicit_default.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -""" -The default cryptographic materials manager (CMM) -is a CMM that uses a keyring or master key provider -to manage the data key materials. -When using the encrypt and decrypt APIs, as well as the caching CMM, -you can supply either a CMM, a keyring, or a master key provider. -If you supply a keyring or master key provider -those components will automatically wrap it in a default CMM. - -This example shows how you could do this manually if you wanted to. -This can be useful when constructing custom CMMs. -For examples showing how to create custom CMMs, -see the ``crypto_materials_manager/custom`` directory. - -https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager - -In this example, we use an AWS KMS customer master key (CMK), -but you can use other key management options with the AWS Encryption SDK. -For examples that demonstrate how to use other key management configurations, -see the ``keyring`` and ``master_key_provider`` directories. - -In this example, we use the one-step encrypt and decrypt APIs. -""" -import aws_encryption_sdk -from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring -from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager - - -def run(aws_kms_cmk, source_plaintext): - # type: (str, bytes) -> None - """Demonstrate an encrypt/decrypt cycle using a KMS keyring with a single CMK. - - :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys - :param bytes source_plaintext: Plaintext to encrypt - """ - # Prepare your encryption context. - # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context - encryption_context = { - "encryption": "context", - "is not": "secret", - "but adds": "useful metadata", - "that can help you": "be confident that", - "the data you are handling": "is what you think it is", - } - - # Create the keyring that determines how your data keys are protected. - keyring = KmsKeyring(generator_key_id=aws_kms_cmk) - - # Wrap that keyring in the default cryptographic materials manager. - cmm = DefaultCryptoMaterialsManager(keyring=keyring) - - # Encrypt your plaintext data. - ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( - source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm - ) - - # Demonstrate that the ciphertext and plaintext are different. - assert ciphertext != source_plaintext - - # Decrypt your encrypted data using the same cryptographic materials manager you used on encrypt. - # - # You do not need to specify the encryption context on decrypt - # because the header of the encrypted message includes the encryption context. - decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=cmm) - - # Demonstrate that the decrypted plaintext is identical to the original plaintext. - assert decrypted == source_plaintext - - # Verify that the encryption context used in the decrypt operation includes - # the encryption context that you specified when encrypting. - # The AWS Encryption SDK can add pairs, so don't require an exact match. - # - # In production, always use a meaningful encryption context. - assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) From 768884734b28d4c70680eb7c3c22f45f165d8cc3 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 12:46:34 -0700 Subject: [PATCH 06/10] docs: clarify "filtering CMM" references in examples comments --- .../custom/algorithm_suite_enforcement.py | 8 ++++---- .../requiring_encryption_context_fields.py | 17 +++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py index 902cd7bb8..a743b0379 100644 --- a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py +++ b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py @@ -79,10 +79,10 @@ def run(aws_kms_cmk, source_plaintext): # Create the keyring that determines how your data keys are protected. keyring = KmsKeyring(generator_key_id=aws_kms_cmk) - # Create the filtering cryptographic materials manager using your keyring. + # Create the algorithm suite restricting cryptographic materials manager using your keyring. cmm = OnlyKdfAlgorithmSuitesCryptoMaterialsManager(keyring=keyring) - # Demonstrate that the filtering CMM will not let you use non-KDF algorithm suites. + # Demonstrate that the algorithm suite restricting CMM will not let you use non-KDF algorithm suites. try: aws_encryption_sdk.encrypt( source=source_plaintext, @@ -95,8 +95,8 @@ def run(aws_kms_cmk, source_plaintext): # Reaching this point means everything is working as expected. pass else: - # The filtering CMM keeps this from happening. - raise AssertionError("The filtering CMM does not let this happen!") + # The algorithm suite restricting CMM keeps this from happening. + raise AssertionError("The algorithm suite restricting CMM does not let this happen!") # Encrypt your plaintext data. ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( diff --git a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py index d84240fa0..6bb55202e 100644 --- a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py +++ b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py @@ -85,10 +85,10 @@ def run(aws_kms_cmk, source_plaintext): # Create the keyring that determines how your data keys are protected. keyring = KmsKeyring(generator_key_id=aws_kms_cmk) - # Create the filtering cryptographic materials manager using your keyring. + # Create the classification requiring cryptographic materials manager using your keyring. cmm = ClassificationRequiringCryptoMaterialsManager(keyring=keyring) - # Demonstrate that the filtering CMM will not let you encrypt without a classification identifier. + # Demonstrate that the classification requiring CMM will not let you encrypt without a classification identifier. try: aws_encryption_sdk.encrypt( source=source_plaintext, encryption_context=encryption_context, materials_manager=cmm, @@ -98,8 +98,8 @@ def run(aws_kms_cmk, source_plaintext): # Reaching this point means everything is working as expected. pass else: - # The filtering CMM keeps this from happening. - raise AssertionError("The filtering CMM does not let this happen!") + # The classification requiring CMM keeps this from happening. + raise AssertionError("The classification requiring CMM does not let this happen!") # Encrypt your plaintext data. classified_ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( @@ -127,7 +127,7 @@ def run(aws_kms_cmk, source_plaintext): # In production, always use a meaningful encryption context. assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) - # Now demonstrate the decrypt path of the filtering cryptographic materials manager. + # Now demonstrate the decrypt path of the classification requiring cryptographic materials manager. # Encrypt your plaintext using the keyring and do not include a classification identifier. unclassified_ciphertext, encrypt_header = aws_encryption_sdk.encrypt( @@ -136,7 +136,8 @@ def run(aws_kms_cmk, source_plaintext): assert "classification" not in encrypt_header.encryption_context - # Demonstrate that the filtering CMM will not let you decrypt messages without classification identifiers. + # Demonstrate that the classification requiring CMM + # will not let you decrypt messages without classification identifiers. try: aws_encryption_sdk.decrypt(source=unclassified_ciphertext, materials_manager=cmm) except MissingClassificationError: @@ -144,5 +145,5 @@ def run(aws_kms_cmk, source_plaintext): # Reaching this point means everything is working as expected. pass else: - # The filtering CMM keeps this from happening. - raise AssertionError("The filtering CMM does not let this happen!") + # The classification requiring CMM keeps this from happening. + raise AssertionError("The classification requiring CMM does not let this happen!") From c1ed9c0f3d0805af944e8ca2fef8f36c7bbcf12a Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 13:30:13 -0700 Subject: [PATCH 07/10] chore: autoformat --- test/unit/keyrings/test_aws_kms.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/unit/keyrings/test_aws_kms.py b/test/unit/keyrings/test_aws_kms.py index 78f84635e..2adf0f656 100644 --- a/test/unit/keyrings/test_aws_kms.py +++ b/test/unit/keyrings/test_aws_kms.py @@ -42,10 +42,7 @@ def test_kms_keyring_builds_correct_inner_keyring_multikeyring(): supplier = DefaultClientSupplier() test = KmsKeyring( - generator_key_id=generator_id, - key_ids=(child_id_1, child_id_2), - grant_tokens=grants, - client_supplier=supplier, + generator_key_id=generator_id, key_ids=(child_id_1, child_id_2), grant_tokens=grants, client_supplier=supplier, ) # We specified a generator and child IDs, so the inner keyring MUST be a multikeyring From b83fdf28cfecbd205cb97e79f2a74418fe0e0b6a Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 13:31:05 -0700 Subject: [PATCH 08/10] docs: refactor algorithm restricting example focus --- .../custom/algorithm_suite_enforcement.py | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py index a743b0379..35b249c2d 100644 --- a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py +++ b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py @@ -8,12 +8,22 @@ By default, the AWS Encryption SDK will let you use any of these, but you might want to restrict that further. -We do not recommend using the algorithm suites without key derivation, -so for this example we will show how to make a custom CMM -that will not allow you to use those algorithm suites. + +We recommend that you use the default algorithm suite, +which uses AES-GCM with 256-bit keys, HKDF, and ECDSA message signing. +If your readers and writers have the same permissions, +you might want to omit the message signature for faster operation. +For more information about choosing a signed or unsigned algorithm suite, +see the AWS Encryption SDK developer guide: + +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/supported-algorithms.html#other-algorithms + +This example shows how you can make a custom cryptographic materials manager (CMM) +that only allows encrypt requests that either specify one of these two algorithm suites +or do not specify an algorithm suite, in which case the default CMM uses the default algorithm suite, """ import aws_encryption_sdk -from aws_encryption_sdk.identifiers import AlgorithmSuite, KDFSuite +from aws_encryption_sdk.identifiers import AlgorithmSuite from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring from aws_encryption_sdk.keyrings.base import Keyring from aws_encryption_sdk.materials_managers import ( @@ -26,12 +36,12 @@ from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager -class UnsupportedAlgorithmSuite(Exception): +class UnapprovedAlgorithmSuite(Exception): """Indicate that an unsupported algorithm suite was requested.""" -class OnlyKdfAlgorithmSuitesCryptoMaterialsManager(CryptoMaterialsManager): - """Only allow encryption requests for algorithm suites with a KDF.""" +class RequireApprovedAlgorithmSuitesCryptoMaterialsManager(CryptoMaterialsManager): + """Only allow encryption requests for approved algorithm suites.""" def __init__(self, keyring): # type: (Keyring) -> None @@ -39,6 +49,11 @@ def __init__(self, keyring): :param Keyring keyring: Keyring to use in the inner cryptographic materials manager """ + self._allowed_algorithm_suites = { + None, # no algorithm suite in the request + AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, # the default algorithm suite + AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA256, # the recommended unsigned algorithm suite + } # Wrap the provided keyring in the default cryptographic materials manager (CMM). # # This is the same thing that the encrypt and decrypt APIs, as well as the caching CMM, @@ -47,9 +62,9 @@ def __init__(self, keyring): def get_encryption_materials(self, request): # type: (EncryptionMaterialsRequest) -> EncryptionMaterials - """Block any requests that include an algorithm suite without a KDF.""" - if request.algorithm is not None and request.algorithm.kdf is KDFSuite.NONE: - raise UnsupportedAlgorithmSuite("Non-KDF algorithm suites are not allowed!") + """Block any requests that include an approved algorithm suite.""" + if request.algorithm not in self._allowed_algorithm_suites: + raise UnapprovedAlgorithmSuite("Unapproved algorithm suite requested!") return self._cmm.get_encryption_materials(request) @@ -80,9 +95,9 @@ def run(aws_kms_cmk, source_plaintext): keyring = KmsKeyring(generator_key_id=aws_kms_cmk) # Create the algorithm suite restricting cryptographic materials manager using your keyring. - cmm = OnlyKdfAlgorithmSuitesCryptoMaterialsManager(keyring=keyring) + cmm = RequireApprovedAlgorithmSuitesCryptoMaterialsManager(keyring=keyring) - # Demonstrate that the algorithm suite restricting CMM will not let you use non-KDF algorithm suites. + # Demonstrate that the algorithm suite restricting CMM will not let you use an unapproved algorithm suite. try: aws_encryption_sdk.encrypt( source=source_plaintext, @@ -90,8 +105,8 @@ def run(aws_kms_cmk, source_plaintext): materials_manager=cmm, algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16, ) - except UnsupportedAlgorithmSuite: - # You asked for a non-KDF algorithm suite. + except UnapprovedAlgorithmSuite: + # You asked for an unapproved algorithm suite. # Reaching this point means everything is working as expected. pass else: From 21025423828f0f805bba9c9fb2c93cea1543ba2c Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 9 Apr 2020 13:34:35 -0700 Subject: [PATCH 09/10] docs: revise framing of encryption context example and KMS references --- .../custom/requiring_encryption_context_fields.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py index 6bb55202e..c797849bb 100644 --- a/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py +++ b/examples/src/crypto_materials_manager/custom/requiring_encryption_context_fields.py @@ -3,12 +3,16 @@ """ Encryption context is a powerful tool for access and audit controls because it lets you tie *non-secret* metadata about a plaintext value to the encrypted message. -This is especially powerful when you use the AWS Encryption SDK with AWS KMS, -but within the context of the AWS Encryption SDK alone +Within the AWS Encryption SDK, you can use cryptographic materials managers to analyse the encryption context to provide logical controls and additional metadata. https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + +If you are using the AWS Encryption SDK with AWS KMS, +you can use AWS KMS to provide additional powerful controls using the encryption context. +For more information on that, see the KMS developer guide: + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context This example shows how to create a custom cryptographic materials manager (CMM) From 1445c3739827aebc2837e6bd6ba59e2cf899459e Mon Sep 17 00:00:00 2001 From: Matt Bullock Date: Thu, 9 Apr 2020 15:32:29 -0700 Subject: [PATCH 10/10] docs: apply suggestions from code review Co-Authored-By: Wesley Rosenblum <55108558+WesleyRosenblum@users.noreply.github.com> --- .../custom/algorithm_suite_enforcement.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py index 35b249c2d..d7385fc76 100644 --- a/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py +++ b/examples/src/crypto_materials_manager/custom/algorithm_suite_enforcement.py @@ -20,7 +20,7 @@ This example shows how you can make a custom cryptographic materials manager (CMM) that only allows encrypt requests that either specify one of these two algorithm suites -or do not specify an algorithm suite, in which case the default CMM uses the default algorithm suite, +or do not specify an algorithm suite, in which case the default CMM uses the default algorithm suite. """ import aws_encryption_sdk from aws_encryption_sdk.identifiers import AlgorithmSuite @@ -62,7 +62,7 @@ def __init__(self, keyring): def get_encryption_materials(self, request): # type: (EncryptionMaterialsRequest) -> EncryptionMaterials - """Block any requests that include an approved algorithm suite.""" + """Block any requests that include an unapproved algorithm suite.""" if request.algorithm not in self._allowed_algorithm_suites: raise UnapprovedAlgorithmSuite("Unapproved algorithm suite requested!")