-
Notifications
You must be signed in to change notification settings - Fork 85
chore: added keyring examples (kms_rsa, multi, discovery) #671
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
RitvikKapila
merged 184 commits into
mpl-reviewed
from
rkapila/multi-discovery-kmsrsa-keyrings
May 3, 2024
Merged
Changes from 180 commits
Commits
Show all changes
184 commits
Select commit
Hold shift + click to select a range
7360edd
passing hierarchy keyring example
lucasmcdonald3 53c46ec
cleanup
lucasmcdonald3 3f5a503
add
lucasmcdonald3 16cf5c1
changes, cleanup:
lucasmcdonald3 5b5aa07
changes, cleanup
lucasmcdonald3 03e19ca
flake8
lucasmcdonald3 b5d3327
flake8
lucasmcdonald3 b13cd19
flake8
lucasmcdonald3 51065cb
flake8
lucasmcdonald3 fc4d254
flake8
lucasmcdonald3 a8e52d3
fix pem/der
lucasmcdonald3 6f55047
fix pem/der
lucasmcdonald3 1b1b4e4
debug
lucasmcdonald3 38a4cc9
debug
lucasmcdonald3 0cd0e23
fix
lucasmcdonald3 44826a2
fix
lucasmcdonald3 02e9f84
fix
lucasmcdonald3 a3babfd
linter
lucasmcdonald3 d2c974a
linter
lucasmcdonald3 55b24a8
isort
lucasmcdonald3 7e5fa48
flake8 examples
lucasmcdonald3 055deab
isort + flake8
lucasmcdonald3 6cf01d4
flake8/pylint examples
lucasmcdonald3 00cfed1
reset tests
lucasmcdonald3 61bbb3b
extend mpl
lucasmcdonald3 4d53ad6
mpl gha
lucasmcdonald3 c1736d3
debug
lucasmcdonald3 9991789
debug
lucasmcdonald3 a501e8f
debug
lucasmcdonald3 6eb8f82
debug
lucasmcdonald3 5ccfa0c
codebuild mpl
lucasmcdonald3 5e7ec9b
codebuild mpl
lucasmcdonald3 cc48697
codebuild mpl
lucasmcdonald3 fae43d1
codebuild mpl
lucasmcdonald3 2637616
debug
lucasmcdonald3 2694932
debug
lucasmcdonald3 f674d3e
debug
lucasmcdonald3 0b5e655
debug
lucasmcdonald3 831df17
debug
lucasmcdonald3 477e3a0
debug
lucasmcdonald3 166c5ab
debug
lucasmcdonald3 7ac8880
debug
lucasmcdonald3 8193c25
Merge branch 'master' into lucmcdon/mpl
lucasmcdonald3 7e3ca15
fix
lucasmcdonald3 4c6a1d0
fix
lucasmcdonald3 e2e1858
fix
lucasmcdonald3 c790011
mpl
lucasmcdonald3 33ace58
fix
lucasmcdonald3 cbf2cdf
fix
lucasmcdonald3 b259477
fix
lucasmcdonald3 9d52cf2
.
lucasmcdonald3 31b7616
debug tox mpl keystore env
lucasmcdonald3 353b8cf
debug tox mpl keystore env
lucasmcdonald3 fb64d95
debug tox mpl keystore env
lucasmcdonald3 916ae8e
debug tox mpl keystore env
lucasmcdonald3 222b135
debug tox mpl keystore env
lucasmcdonald3 cab6016
some unit tests
lucasmcdonald3 a7416b1
add mpl coverage
lucasmcdonald3 7b3dc5f
.
lucasmcdonald3 7a5e4eb
.
lucasmcdonald3 0649995
mock imports
lucasmcdonald3 6691fa2
refactor, fix
lucasmcdonald3 3ae1e06
refactor, fix
lucasmcdonald3 2b5fc72
refactor, fix
lucasmcdonald3 a940dc5
refactor, fix
lucasmcdonald3 708ab5e
it works locally but fails on gha
lucasmcdonald3 ffd295c
it works locally but fails on gha
lucasmcdonald3 1ba175c
it works locally but fails on gha
lucasmcdonald3 fa175ba
it works locally but fails on gha
lucasmcdonald3 2f90a97
it works locally but fails on gha
lucasmcdonald3 df9215f
it works locally but fails on gha
lucasmcdonald3 b57e4a3
it works locally but fails on gha
lucasmcdonald3 9d7ec6d
it works locally but fails on gha
lucasmcdonald3 2cbc845
it works locally but fails on gha
lucasmcdonald3 def946d
it works locally but fails on gha
lucasmcdonald3 dff6ac0
it works locally but fails on gha
lucasmcdonald3 78f0b0f
it works locally but fails on gha
lucasmcdonald3 20a469e
it works locally but fails on gha
lucasmcdonald3 66859a7
fix tests
lucasmcdonald3 bf8f67c
cleanup
lucasmcdonald3 b24be11
re-enable test
lucasmcdonald3 acba1b0
re-enable test
lucasmcdonald3 42b7b74
longpaths
lucasmcdonald3 f226e7e
longpaths
lucasmcdonald3 aa2f80a
debug windows fail
lucasmcdonald3 bc002b6
debug windows fail
lucasmcdonald3 8dd0303
debug windows fail
lucasmcdonald3 1e9db3b
debug windows fail
lucasmcdonald3 74d4e66
disable windows until pythonpath
lucasmcdonald3 1bb23e8
expand testing
lucasmcdonald3 1ee69ce
expand testing
lucasmcdonald3 b33f2f7
expand testing
lucasmcdonald3 c582888
expand testing
lucasmcdonald3 5ae44f5
expand testing
lucasmcdonald3 cb7e3d1
cleanup
lucasmcdonald3 b026b53
cleanup
lucasmcdonald3 50afa3a
cleanup
lucasmcdonald3 1c612a0
cleanup
lucasmcdonald3 bcdb4ba
add missing file
lucasmcdonald3 41fe2f9
add missing file
lucasmcdonald3 1ba857e
add missing file
lucasmcdonald3 74bfe12
cleanup
lucasmcdonald3 b3b9a0f
refactor
lucasmcdonald3 a594125
refactor
lucasmcdonald3 fdd2eda
unit tests
lucasmcdonald3 0138f22
unit tests
lucasmcdonald3 f213e19
upgrade image
lucasmcdonald3 d55f296
refactor tests
lucasmcdonald3 5ec4668
refactor tests
lucasmcdonald3 61ba4de
refactor tests
lucasmcdonald3 95c5be6
refactor tests
lucasmcdonald3 9566873
refactor tests
lucasmcdonald3 6642083
fix cov
lucasmcdonald3 51d2804
fix cov
lucasmcdonald3 51e5db5
fix cov
lucasmcdonald3 e235461
fix cov
lucasmcdonald3 e7c745f
fix tests
lucasmcdonald3 fee4f36
test cleanup
lucasmcdonald3 ac6471a
test cleanup
lucasmcdonald3 a5ebc19
isort
lucasmcdonald3 21f3614
fixes
lucasmcdonald3 22eabb6
fix
lucasmcdonald3 ac0ceb3
fix
lucasmcdonald3 2fd8858
oops
lucasmcdonald3 51c6a9c
revert
lucasmcdonald3 800f9de
revert
lucasmcdonald3 ebcb759
fix
lucasmcdonald3 cf26ca3
fix
lucasmcdonald3 7f27ebd
fix
lucasmcdonald3 00f4721
fix
lucasmcdonald3 018b93f
fix
lucasmcdonald3 d413b65
fix
lucasmcdonald3 c4ca658
copyright
lucasmcdonald3 d99b666
more unit tests
lucasmcdonald3 49cb7c8
more unit tests
lucasmcdonald3 705113a
more unit tests
lucasmcdonald3 f76d7f9
more unit tests
lucasmcdonald3 0da2a4f
more unit tests
lucasmcdonald3 0040b2c
cleanup
lucasmcdonald3 9131433
cleanup
lucasmcdonald3 e6826eb
poc impl
lucasmcdonald3 a9fa1a5
passing
lucasmcdonald3 4eeb858
cleanup
lucasmcdonald3 21a8c93
protect
lucasmcdonald3 de870b8
ex
lucasmcdonald3 eedf1a3
changes
lucasmcdonald3 1db73eb
changes
lucasmcdonald3 8415c2c
cleanup
lucasmcdonald3 20bdaff
cleanup
lucasmcdonald3 6bf6094
cleanup
lucasmcdonald3 febe6db
cleanup
lucasmcdonald3 dc8abca
cleanup
lucasmcdonald3 8ff46f4
cleanup
lucasmcdonald3 aba7ccc
cleanup
lucasmcdonald3 40fecc0
all message format versions
lucasmcdonald3 52043b9
sync upstream
lucasmcdonald3 14c287d
Merge
lucasmcdonald3 2d26009
Merge branch 'lucmcdon/mpl' into lucmcdon/mpl-requiredec
lucasmcdonald3 7374fcb
unit tests
lucasmcdonald3 f9d60a8
lint
lucasmcdonald3 16725f8
lint
lucasmcdonald3 1706db2
lint
lucasmcdonald3 06e0842
lint
lucasmcdonald3 5ad8e3a
Update examples/src/keyrings/hierarchical_keyring.py
lucasmcdonald3 280e038
Update examples/src/keyrings/hierarchical_keyring.py
lucasmcdonald3 437b81d
chore: kms rsa keyring example
RitvikKapila 5bf8d2b
adding more keyrings
RitvikKapila 41f901b
chore: updated multi, discovery and discovery multi keyrings
RitvikKapila 731c698
chore: fixed naming in test_i_multi_keyring_example.py, added aws_kms…
RitvikKapila 8bd9383
fix: updated aws_kms_rsa_keyring
RitvikKapila f7a0a7a
fix
RitvikKapila c124ebb
Merge branch 'mpl-reviewed' into rkapila/multi-discovery-kmsrsa-keyrings
RitvikKapila 86845ea
fix
RitvikKapila ca8943b
fix
RitvikKapila c56e924
fix(-)
RitvikKapila 3c7292b
fix
RitvikKapila 7cb5864
update
RitvikKapila d2b79c9
fix cb
lucasmcdonald3 324f683
fix
lucasmcdonald3 8c9d4b1
fix: unit tests for _native_algorithm_id_to_mpl_algorithm_id
RitvikKapila 3c41753
fixed comments
RitvikKapila 036662f
fix
RitvikKapila cbf72ff
Update aws_kms_rsa_keyring_example.py
RitvikKapila 41e40f3
fix
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
201 changes: 201 additions & 0 deletions
201
examples/src/keyrings/aws_kms_discovery_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,201 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example sets up the AWS KMS Discovery Keyring | ||
|
||
AWS KMS discovery keyring is an AWS KMS keyring that doesn't specify any wrapping keys. | ||
|
||
The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring | ||
for AWS KMS multi-Region keys. For information about using multi-Region keys with the | ||
AWS Encryption SDK, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks | ||
|
||
Because it doesn't specify any wrapping keys, a discovery keyring can't encrypt data. | ||
If you use a discovery keyring to encrypt data, alone or in a multi-keyring, the encrypt | ||
operation fails. The exception is the AWS Encryption SDK for C, where the encrypt operation | ||
ignores a standard discovery keyring, but fails if you specify a multi-Region discovery | ||
keyring, alone or in a multi-keyring. | ||
|
||
When decrypting, a discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt | ||
any encrypted data key by using the AWS KMS key that encrypted it, regardless of who owns or | ||
has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt | ||
permission on the AWS KMS key. | ||
|
||
This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA | ||
with an encryption context. This encrypted ciphertext is then decrypted using the Discovery keyring. | ||
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. Decryption is only possible if the Discovery Keyring contains the correct AWS Account ID's to | ||
which the KMS key used for encryption belongs | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 Discovery keyrings, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery | ||
""" | ||
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 ( | ||
CreateAwsKmsDiscoveryKeyringInput, | ||
CreateAwsKmsKeyringInput, | ||
DiscoveryFilter, | ||
) | ||
from aws_cryptographic_materialproviders.mpl.references import IKeyring | ||
from typing import Dict | ||
|
||
import aws_encryption_sdk | ||
from aws_encryption_sdk import CommitmentPolicy | ||
from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError | ||
|
||
# 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( | ||
kms_key_id: str | ||
): | ||
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Keyring. | ||
|
||
Usage: encrypt_and_decrypt_with_keyring(kms_key_id) | ||
:param kms_key_id: KMS Key identifier for the KMS key you want to use for creating | ||
the kms_keyring used for encryption | ||
:type kms_key_id: 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 a boto3 client for KMS. | ||
kms_client = boto3.client('kms', region_name="us-west-2") | ||
|
||
# 3. 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", | ||
} | ||
|
||
# 4. Create the keyring that determines how your data keys are protected. | ||
# Although this example highlights Discovery keyrings, Discovery keyrings cannot | ||
# be used to encrypt, so for encryption we create a KMS keyring without discovery mode. | ||
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( | ||
config=MaterialProvidersConfig() | ||
) | ||
|
||
kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( | ||
kms_key_id=kms_key_id, | ||
kms_client=kms_client | ||
) | ||
|
||
encrypt_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( | ||
input=kms_keyring_input | ||
) | ||
|
||
# 5. Encrypt the data for the encryptionContext | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ciphertext, _ = client.encrypt( | ||
source=EXAMPLE_DATA, | ||
keyring=encrypt_kms_keyring, | ||
encryption_context=encryption_context | ||
) | ||
|
||
# 6. 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" | ||
|
||
# 7. Now create a Discovery keyring to use for decryption. We'll add a discovery filter | ||
# so that we limit the set of ciphertexts we are willing to decrypt to only ones | ||
# created by KMS keys in our account and partition. | ||
discovery_keyring_input: CreateAwsKmsDiscoveryKeyringInput = CreateAwsKmsDiscoveryKeyringInput( | ||
kms_client=kms_client, | ||
discovery_filter=DiscoveryFilter( | ||
account_ids=["658956600833"], | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
partition="aws" | ||
) | ||
) | ||
|
||
discovery_keyring: IKeyring = mat_prov.create_aws_kms_discovery_keyring( | ||
input=discovery_keyring_input | ||
) | ||
|
||
# 8. Decrypt your encrypted data using the discovery keyring. | ||
# On Decrypt, the header of the encrypted message (ciphertext) will be parsed. | ||
# The header contains the Encrypted Data Keys (EDKs), which, if the EDK | ||
# was encrypted by a KMS Keyring, includes the KMS Key ARN. | ||
# The Discovery Keyring filters these EDKs for | ||
# EDKs encrypted by Single Region OR Multi Region KMS Keys. | ||
# If a Discovery Filter is present, these KMS Keys must belong | ||
# to an AWS Account ID in the discovery filter's AccountIds and | ||
# must be from the discovery filter's partition. | ||
# Finally, KMS is called to decrypt each filtered EDK until an EDK is | ||
# successfully decrypted. The resulting data key is used to decrypt the | ||
# ciphertext's message. | ||
# If all calls to KMS fail, the decryption fails. | ||
plaintext_bytes, dec_header = client.decrypt( | ||
source=ciphertext, | ||
keyring=discovery_keyring | ||
) | ||
|
||
# 9. 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" | ||
|
||
# 10. 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 | ||
|
||
# 11. Demonstrate that if a discovery keyring (Bob's) doesn't have the correct AWS Account ID's, | ||
# the decrypt will fail with an error message | ||
# Note that the Account ID '888888888888' used here is different than the one used | ||
# during encryption '658956600833' | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
discovery_keyring_input_bob: CreateAwsKmsDiscoveryKeyringInput = \ | ||
CreateAwsKmsDiscoveryKeyringInput( | ||
kms_client=kms_client, | ||
discovery_filter=DiscoveryFilter( | ||
account_ids=["888888888888"], | ||
partition="aws" | ||
) | ||
) | ||
|
||
discovery_keyring_bob: IKeyring = mat_prov.create_aws_kms_discovery_keyring( | ||
input=discovery_keyring_input_bob | ||
) | ||
|
||
# Decrypt the ciphertext using Bob's discovery keyring which doesn't contain the required | ||
# Account ID's for the KMS keyring used for encryption. | ||
# This should throw an AWSEncryptionSDKClientError exception | ||
try: | ||
plaintext_bytes, _ = client.decrypt( | ||
source=ciphertext, | ||
keyring=discovery_keyring_bob | ||
) | ||
|
||
raise AssertionError("Decrypt using discovery keyring with wrong AWS Account ID should" | ||
+ "raise AWSEncryptionSDKClientError") | ||
except AWSEncryptionSDKClientError: | ||
pass |
169 changes: 169 additions & 0 deletions
169
examples/src/keyrings/aws_kms_discovery_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,169 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example sets up the AWS KMS Discovery Multi Keyring and demonstrates decryption | ||
using a Multi-Keyring containing multiple AWS KMS Discovery Keyrings. | ||
|
||
The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring | ||
for AWS KMS multi-Region keys. For information about using multi-Region keys with the | ||
AWS Encryption SDK, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks | ||
|
||
Because it doesn't specify any wrapping keys, a discovery keyring can't encrypt data. | ||
If you use a discovery keyring to encrypt data, alone or in a multi-keyring, the encrypt | ||
operation fails. The exception is the AWS Encryption SDK for C, where the encrypt operation | ||
ignores a standard discovery keyring, but fails if you specify a multi-Region discovery | ||
keyring, alone or in a multi-keyring. | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
When decrypting, a discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt | ||
any encrypted data key by using the AWS KMS key that encrypted it, regardless of who owns or | ||
has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt | ||
permission on the AWS KMS key. | ||
|
||
This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA | ||
with an encryption context. This encrypted ciphertext is then decrypted using the Discovery Multi | ||
keyring. 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. | ||
|
||
For more information on how to use KMS Discovery keyrings, see | ||
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery | ||
""" | ||
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 ( | ||
CreateAwsKmsDiscoveryMultiKeyringInput, | ||
CreateAwsKmsKeyringInput, | ||
DiscoveryFilter, | ||
) | ||
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( | ||
kms_key_id: str | ||
): | ||
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Multi Keyring. | ||
|
||
Usage: encrypt_and_decrypt_with_keyring(kms_key_id) | ||
:param kms_key_id: KMS Key identifier for the KMS key you want to use for creating | ||
the kms_keyring used for encryption | ||
:type kms_key_id: 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 a boto3 client for KMS. | ||
kms_client = boto3.client('kms', region_name="us-west-2") | ||
|
||
# 3. 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", | ||
} | ||
|
||
# 4. Create the keyring that determines how your data keys are protected. | ||
# Although this example highlights Discovery keyrings, Discovery keyrings cannot | ||
# be used to encrypt, so for encryption we create a KMS keyring without discovery mode. | ||
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( | ||
config=MaterialProvidersConfig() | ||
) | ||
|
||
kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( | ||
kms_key_id=kms_key_id, | ||
kms_client=kms_client | ||
) | ||
|
||
encrypt_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( | ||
input=kms_keyring_input | ||
) | ||
|
||
# 5. Encrypt the data for the encryptionContext | ||
ciphertext, _ = client.encrypt( | ||
source=EXAMPLE_DATA, | ||
keyring=encrypt_kms_keyring, | ||
encryption_context=encryption_context | ||
) | ||
|
||
# 6. 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" | ||
|
||
# 7. Now create a Discovery Multi keyring to use for decryption. We'll add a discovery filter | ||
# so that we limit the set of ciphertexts we are willing to decrypt to only ones | ||
# created by KMS keys in our account and partition. | ||
discovery_multi_keyring_input: CreateAwsKmsDiscoveryMultiKeyringInput = \ | ||
CreateAwsKmsDiscoveryMultiKeyringInput( | ||
regions=["us-west-2", "us-east-1"], | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
discovery_filter=DiscoveryFilter( | ||
account_ids=["658956600833"], | ||
RitvikKapila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
partition="aws" | ||
) | ||
) | ||
|
||
# This is a Multi Keyring composed of Discovery Keyrings. | ||
# There is a keyring for every region in `regions`. | ||
# All the keyrings have the same Discovery Filter. | ||
# Each keyring has its own KMS Client, which is created for the keyring's region. | ||
discovery_multi_keyring: IKeyring = mat_prov.create_aws_kms_discovery_multi_keyring( | ||
input=discovery_multi_keyring_input | ||
) | ||
|
||
# 8. On Decrypt, the header of the encrypted message (ciphertext) will be parsed. | ||
# The header contains the Encrypted Data Keys (EDKs), which, if the EDK | ||
# was encrypted by a KMS Keyring, includes the KMS Key ARN. | ||
# For each member of the Multi Keyring, every EDK will try to be decrypted until a decryption | ||
# is successful. | ||
# Since every member of the Multi Keyring is a Discovery Keyring: | ||
# Each Keyring will filter the EDKs by the Discovery Filter | ||
# For the filtered EDKs, the keyring will try to decrypt it with the keyring's client. | ||
# All of this is done serially, until a success occurs or all keyrings have | ||
# failed all (filtered) EDKs. | ||
# KMS Discovery Keyrings will attempt to decrypt Multi Region Keys (MRKs) and regular KMS Keys. | ||
plaintext_bytes, dec_header = client.decrypt( | ||
source=ciphertext, | ||
keyring=discovery_multi_keyring | ||
) | ||
|
||
# 9. 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" | ||
|
||
# 10. 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 |
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.