-
Notifications
You must be signed in to change notification settings - Fork 86
chore(examples): Added mrk and mrk_multi keyring examples #673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
9187a08
mrk
RitvikKapila 05abfa9
fix mrk
RitvikKapila 9297b8b
added kms mrk and mrk multi keyrings
RitvikKapila c5f249e
minor fix
RitvikKapila aa727ab
minor fix
RitvikKapila 88ee2c0
fix
RitvikKapila 8e152e3
fix (2)
RitvikKapila File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example sets up the KMS MRK (multi-region key) Keyring | ||
|
||
The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to | ||
create, encrypt, and decrypt data keys with multi-region AWS KMS keys (MRKs). | ||
This example creates a KMS MRK Keyring and then encrypts a custom input EXAMPLE_DATA | ||
with an encryption context. This example also includes some sanity checks for demonstration: | ||
1. Ciphertext and plaintext data are not the same | ||
2. Encryption context is correct in the decrypted message header | ||
3. Decrypted plaintext value matches EXAMPLE_DATA | ||
These sanity checks are for demonstration in the example only. You do not need these in your code. | ||
|
||
AWS KMS MRK keyrings can be used independently or in a multi-keyring with other keyrings | ||
of the same or a different type. | ||
|
||
For more information on how to use KMS keyrings, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html | ||
|
||
For more info on KMS MRK (multi-region keys), see the KMS documentation: | ||
https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html | ||
""" | ||
import sys | ||
|
||
import boto3 | ||
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders | ||
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig | ||
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput | ||
from aws_cryptographic_materialproviders.mpl.references import IKeyring | ||
from typing import Dict | ||
|
||
import aws_encryption_sdk | ||
from aws_encryption_sdk import CommitmentPolicy | ||
|
||
# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. | ||
MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) | ||
|
||
sys.path.append(MODULE_ROOT_DIR) | ||
|
||
EXAMPLE_DATA: bytes = b"Hello World" | ||
|
||
|
||
def encrypt_and_decrypt_with_keyring( | ||
mrk_key_id_encrypt: str, | ||
mrk_replica_key_id_decrypt: str, | ||
default_region: str, | ||
second_region: str | ||
): | ||
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS MRK keyring. | ||
|
||
Usage: encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, | ||
mrk_replica_key_id_decrypt, | ||
default_region, | ||
second_region) | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
:param mrk_key_id_encrypt: KMS Key identifier for the KMS key located in your | ||
default region, which you want to use for encryption of your data keys | ||
:type mrk_key_id_encrypt: string | ||
:param mrk_replica_key_id_decrypt: KMS Key identifier for the KMS key KMS Key | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
that is a replica of the `mrk_key_id_encrypt` in a second region, which you | ||
want to use for decryption of your data keys | ||
:type mrk_replica_key_id_decrypt: string | ||
:param default_region: AWS Region for encryption of your data keys | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
:type default_region: string | ||
:param second_region: AWS Region for decryption of your data keys | ||
:type second_region: string | ||
|
||
For more information on KMS Key identifiers, see | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id | ||
""" | ||
# 1. Instantiate the encryption SDK client. | ||
# This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, | ||
# which enforces that this client only encrypts using committing algorithm suites and enforces | ||
# that this client will only decrypt encrypted messages that were created with a committing | ||
# algorithm suite. | ||
# This is the default commitment policy if you were to build the client as | ||
# `client = aws_encryption_sdk.EncryptionSDKClient()`. | ||
client = aws_encryption_sdk.EncryptionSDKClient( | ||
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT | ||
) | ||
|
||
# 2. Create encryption context. | ||
# Remember that your encryption context is NOT SECRET. | ||
# For more information, see | ||
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||
encryption_context: Dict[str, str] = { | ||
"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", | ||
} | ||
|
||
# 3. Create a keyring that will encrypt your data, using a KMS MRK key in the first region. | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( | ||
config=MaterialProvidersConfig() | ||
) | ||
|
||
# Create a boto3 client for KMS in the first region. | ||
encrypt_kms_client = boto3.client('kms', region_name=default_region) | ||
|
||
encrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( | ||
kms_key_id=mrk_key_id_encrypt, | ||
kms_client=encrypt_kms_client | ||
) | ||
|
||
encrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( | ||
input=encrypt_keyring_input | ||
) | ||
|
||
# 4. Encrypt the data with the encryptionContext using the encrypt_keyring. | ||
ciphertext, _ = client.encrypt( | ||
source=EXAMPLE_DATA, | ||
keyring=encrypt_keyring, | ||
encryption_context=encryption_context | ||
) | ||
|
||
# 5. Demonstrate that the ciphertext and plaintext are different. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
assert ciphertext != EXAMPLE_DATA, \ | ||
"Ciphertext and plaintext data are the same. Invalid encryption" | ||
|
||
# 6. Create a keyring that will decrypt your data, using the same KMS MRK key replicated | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# to the second region. This example assumes you have already replicated your key | ||
|
||
# Create a boto3 client for KMS in the second region. | ||
decrypt_kms_client = boto3.client('kms', region_name=second_region) | ||
|
||
decrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( | ||
kms_key_id=mrk_replica_key_id_decrypt, | ||
kms_client=decrypt_kms_client | ||
) | ||
|
||
decrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( | ||
input=decrypt_keyring_input | ||
) | ||
|
||
# 7. Decrypt your encrypted data using the same keyring you used on encrypt. | ||
plaintext_bytes, dec_header = client.decrypt( | ||
source=ciphertext, | ||
keyring=decrypt_keyring | ||
) | ||
|
||
# 8. Demonstrate that the encryption context is correct in the decrypted message header | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
for k, v in encryption_context.items(): | ||
assert v == dec_header.encryption_context[k], \ | ||
"Encryption context does not match expected values" | ||
|
||
# 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
assert plaintext_bytes == EXAMPLE_DATA |
175 changes: 175 additions & 0 deletions
175
examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example sets up the KMS MRK Multi Keyring | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to | ||
create, encrypt, and decrypt data keys with multi-region AWS KMS keys (MRKs). | ||
This example creates a KMS MRK Multi Keyring using an mrk_key_id (generator) and | ||
a kms_key_id, and then encrypts a custom input EXAMPLE_DATA with an encryption context. | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This example also includes some sanity checks for demonstration: | ||
1. Ciphertext and plaintext data are not the same | ||
2. Encryption context is correct in the decrypted message header | ||
3. Decrypted plaintext value matches EXAMPLE_DATA | ||
4. Ciphertext can be decrypted using an AwsKmsMrkKeyring containing a replica of the | ||
MRK key (from the multi-keyring used for encryption) copied from the first region into | ||
the second region | ||
These sanity checks are for demonstration in the example only. You do not need these in your code. | ||
|
||
For more information on how to use KMS keyrings, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html | ||
""" | ||
import sys | ||
|
||
import boto3 | ||
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders | ||
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig | ||
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput, CreateAwsKmsMrkMultiKeyringInput | ||
from aws_cryptographic_materialproviders.mpl.references import IKeyring | ||
from typing import Dict | ||
|
||
import aws_encryption_sdk | ||
from aws_encryption_sdk import CommitmentPolicy | ||
|
||
# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. | ||
MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) | ||
|
||
sys.path.append(MODULE_ROOT_DIR) | ||
|
||
EXAMPLE_DATA: bytes = b"Hello World" | ||
|
||
|
||
def encrypt_and_decrypt_with_keyring( | ||
mrk_key_id: str, | ||
kms_key_id: str, | ||
mrk_replica_key_id: str, | ||
second_region: str | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
): | ||
"""Demonstrate an encrypt/decrypt cycle using a Multi-Keyring made | ||
up of multiple AWS KMS MRK Keyrings | ||
|
||
Usage: encrypt_and_decrypt_with_keyring(mrk_key_id, | ||
kms_key_id, | ||
mrk_replica_key_id, | ||
second_region) | ||
:param mrk_key_id: KMS Key identifier for an AWS KMS multi-region key (MRK) located in your | ||
default region | ||
:type mrk_key_id: string | ||
:param kms_key_id: KMS Key identifier for a KMS key, possibly located in a different region | ||
than the MRK key | ||
:type kms_key_id: string | ||
:param mrk_replica_key_id: KMS Key identifier for an MRK that is a replica of the | ||
`mrk_key_id` in a second region. | ||
:type mrk_replica_key_id: string | ||
:param second_region: The second region where the MRK replica is located | ||
:type second_region: string | ||
|
||
For more information on KMS Key identifiers, see | ||
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id | ||
""" | ||
# 1. Instantiate the encryption SDK client. | ||
# This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, | ||
# which enforces that this client only encrypts using committing algorithm suites and enforces | ||
# that this client will only decrypt encrypted messages that were created with a committing | ||
# algorithm suite. | ||
# This is the default commitment policy if you were to build the client as | ||
# `client = aws_encryption_sdk.EncryptionSDKClient()`. | ||
client = aws_encryption_sdk.EncryptionSDKClient( | ||
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT | ||
) | ||
|
||
# 2. Create encryption context. | ||
# Remember that your encryption context is NOT SECRET. | ||
# For more information, see | ||
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||
encryption_context: Dict[str, str] = { | ||
"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", | ||
} | ||
|
||
# 3. Create an AwsKmsMrkMultiKeyring that protects your data under two different KMS Keys. | ||
# The Keys can either be regular KMS keys or MRKs. | ||
# Either KMS Key individually is capable of decrypting data encrypted under this keyring. | ||
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( | ||
config=MaterialProvidersConfig() | ||
) | ||
|
||
kms_mrk_multi_keyring_input: CreateAwsKmsMrkMultiKeyringInput =\ | ||
CreateAwsKmsMrkMultiKeyringInput( | ||
generator=mrk_key_id, | ||
kms_key_ids=[kms_key_id] | ||
) | ||
|
||
kms_mrk_multi_keyring: IKeyring = mat_prov.create_aws_kms_mrk_multi_keyring( | ||
input=kms_mrk_multi_keyring_input | ||
) | ||
|
||
# 4. Encrypt the data with the encryptionContext using the kms_mrk_multi_keyring. | ||
ciphertext, _ = client.encrypt( | ||
source=EXAMPLE_DATA, | ||
keyring=kms_mrk_multi_keyring, | ||
encryption_context=encryption_context | ||
) | ||
|
||
# 5. Demonstrate that the ciphertext and plaintext are different. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
assert ciphertext != EXAMPLE_DATA, \ | ||
"Ciphertext and plaintext data are the same. Invalid encryption" | ||
|
||
# 6. Decrypt your encrypted data using the same AwsKmsMrkMultiKeyring you used on encrypt. | ||
# It will decrypt the data using the generator KMS MRK key since that is the first available | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# KMS key on the keyring that is capable of decrypting the data. | ||
plaintext_bytes, dec_header = client.decrypt( | ||
source=ciphertext, | ||
keyring=kms_mrk_multi_keyring | ||
) | ||
|
||
# 7. Demonstrate that the encryption context is correct in the decrypted message header | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
for k, v in encryption_context.items(): | ||
assert v == dec_header.encryption_context[k], \ | ||
"Encryption context does not match expected values" | ||
|
||
# 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
assert plaintext_bytes == EXAMPLE_DATA | ||
|
||
# Demonstrate that a single AwsKmsMrkKeyring configured with a replica of the MRK from the | ||
# multi-keyring used to encrypt the data is also capable of decrypting the data. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
|
||
# 9. Create a single AwsKmsMrkKeyring with the replica KMS MRK from the second region. | ||
|
||
# Create a boto3 client for KMS in the second region. | ||
second_region_kms_client = boto3.client('kms', region_name=second_region) | ||
|
||
second_region_mrk_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( | ||
kms_key_id=mrk_replica_key_id, | ||
kms_client=second_region_kms_client | ||
) | ||
|
||
second_region_mrk_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( | ||
input=second_region_mrk_keyring_input | ||
) | ||
|
||
# 10. Decrypt your encrypted data using the second region AwsKmsMrkKeyring | ||
plaintext_bytes_second_region, dec_header_second_region = client.decrypt( | ||
source=ciphertext, | ||
keyring=second_region_mrk_keyring | ||
) | ||
|
||
# 11. Demonstrate that the encryption context is correct in the decrypted message header | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
for k, v in encryption_context.items(): | ||
assert v == dec_header_second_region.encryption_context[k], \ | ||
"Encryption context does not match expected values" | ||
|
||
# 12. Demonstrate that the decrypted plaintext is identical to the original plaintext. | ||
# (This is an example for demonstration; you do not need to do this in your own code.) | ||
assert plaintext_bytes_second_region == EXAMPLE_DATA | ||
|
||
# Not shown in this example: A KMS Keyring created with `kms_key_id` could also | ||
# decrypt this message. |
22 changes: 22 additions & 0 deletions
22
examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
"""Test suite for the AWS KMS MRK keyring example.""" | ||
import pytest | ||
|
||
from ...src.keyrings.aws_kms_mrk_keyring_example import encrypt_and_decrypt_with_keyring | ||
|
||
pytestmark = [pytest.mark.examples] | ||
|
||
|
||
def test_encrypt_and_decrypt_with_keyring(): | ||
"""Test function for encrypt and decrypt using the AWS KMS MRK Keyring example.""" | ||
mrk_key_id_encrypt = \ | ||
"arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" | ||
mrk_replica_key_id_decrypt = \ | ||
"arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" | ||
default_region = "us-east-1" | ||
second_region = "eu-west-1" | ||
encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, | ||
mrk_replica_key_id_decrypt, | ||
default_region, | ||
second_region) |
20 changes: 20 additions & 0 deletions
20
examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
"""Test suite for the AWS KMS MRK Multi keyring example.""" | ||
import pytest | ||
|
||
from ...src.keyrings.aws_kms_mrk_multi_keyring_example import encrypt_and_decrypt_with_keyring | ||
|
||
pytestmark = [pytest.mark.examples] | ||
|
||
|
||
def test_encrypt_and_decrypt_with_keyring(): | ||
"""Test function for encrypt and decrypt using the AWS KMS MRK Multi Keyring example.""" | ||
mrk_key_id = \ | ||
"arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" | ||
kms_key_id = \ | ||
"arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" | ||
mrk_replica_key_id = \ | ||
"arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" | ||
second_region = "eu-west-1" | ||
encrypt_and_decrypt_with_keyring(mrk_key_id, kms_key_id, mrk_replica_key_id, second_region) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.