Skip to content

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
merged 184 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
184 commits
Select commit Hold shift + click to select a range
7360edd
passing hierarchy keyring example
lucasmcdonald3 Jan 31, 2024
53c46ec
cleanup
lucasmcdonald3 Feb 2, 2024
3f5a503
add
lucasmcdonald3 Feb 2, 2024
16cf5c1
changes, cleanup:
lucasmcdonald3 Feb 2, 2024
5b5aa07
changes, cleanup
lucasmcdonald3 Feb 2, 2024
03e19ca
flake8
lucasmcdonald3 Feb 2, 2024
b5d3327
flake8
lucasmcdonald3 Feb 2, 2024
b13cd19
flake8
lucasmcdonald3 Feb 2, 2024
51065cb
flake8
lucasmcdonald3 Feb 2, 2024
fc4d254
flake8
lucasmcdonald3 Feb 2, 2024
a8e52d3
fix pem/der
lucasmcdonald3 Feb 5, 2024
6f55047
fix pem/der
lucasmcdonald3 Feb 5, 2024
1b1b4e4
debug
lucasmcdonald3 Feb 6, 2024
38a4cc9
debug
lucasmcdonald3 Feb 6, 2024
0cd0e23
fix
lucasmcdonald3 Feb 6, 2024
44826a2
fix
lucasmcdonald3 Feb 7, 2024
02e9f84
fix
lucasmcdonald3 Feb 7, 2024
a3babfd
linter
lucasmcdonald3 Feb 7, 2024
d2c974a
linter
lucasmcdonald3 Feb 7, 2024
55b24a8
isort
lucasmcdonald3 Feb 7, 2024
7e5fa48
flake8 examples
lucasmcdonald3 Feb 7, 2024
055deab
isort + flake8
lucasmcdonald3 Feb 7, 2024
6cf01d4
flake8/pylint examples
lucasmcdonald3 Feb 7, 2024
00cfed1
reset tests
lucasmcdonald3 Feb 7, 2024
61bbb3b
extend mpl
lucasmcdonald3 Feb 7, 2024
4d53ad6
mpl gha
lucasmcdonald3 Feb 7, 2024
c1736d3
debug
lucasmcdonald3 Feb 7, 2024
9991789
debug
lucasmcdonald3 Feb 7, 2024
a501e8f
debug
lucasmcdonald3 Feb 7, 2024
6eb8f82
debug
lucasmcdonald3 Feb 7, 2024
5ccfa0c
codebuild mpl
lucasmcdonald3 Feb 7, 2024
5e7ec9b
codebuild mpl
lucasmcdonald3 Feb 7, 2024
cc48697
codebuild mpl
lucasmcdonald3 Feb 7, 2024
fae43d1
codebuild mpl
lucasmcdonald3 Feb 7, 2024
2637616
debug
lucasmcdonald3 Feb 7, 2024
2694932
debug
lucasmcdonald3 Feb 7, 2024
f674d3e
debug
lucasmcdonald3 Feb 7, 2024
0b5e655
debug
lucasmcdonald3 Feb 7, 2024
831df17
debug
lucasmcdonald3 Feb 7, 2024
477e3a0
debug
lucasmcdonald3 Feb 7, 2024
166c5ab
debug
lucasmcdonald3 Feb 7, 2024
7ac8880
debug
lucasmcdonald3 Feb 7, 2024
8193c25
Merge branch 'master' into lucmcdon/mpl
lucasmcdonald3 Feb 7, 2024
7e3ca15
fix
lucasmcdonald3 Feb 7, 2024
4c6a1d0
fix
lucasmcdonald3 Feb 7, 2024
e2e1858
fix
lucasmcdonald3 Feb 7, 2024
c790011
mpl
lucasmcdonald3 Feb 7, 2024
33ace58
fix
lucasmcdonald3 Feb 7, 2024
cbf2cdf
fix
lucasmcdonald3 Feb 7, 2024
b259477
fix
lucasmcdonald3 Feb 7, 2024
9d52cf2
.
lucasmcdonald3 Feb 8, 2024
31b7616
debug tox mpl keystore env
lucasmcdonald3 Feb 9, 2024
353b8cf
debug tox mpl keystore env
lucasmcdonald3 Feb 9, 2024
fb64d95
debug tox mpl keystore env
lucasmcdonald3 Feb 9, 2024
916ae8e
debug tox mpl keystore env
lucasmcdonald3 Feb 9, 2024
222b135
debug tox mpl keystore env
lucasmcdonald3 Feb 9, 2024
cab6016
some unit tests
lucasmcdonald3 Feb 10, 2024
a7416b1
add mpl coverage
lucasmcdonald3 Feb 13, 2024
7b3dc5f
.
lucasmcdonald3 Feb 13, 2024
7a5e4eb
.
lucasmcdonald3 Feb 13, 2024
0649995
mock imports
lucasmcdonald3 Feb 13, 2024
6691fa2
refactor, fix
lucasmcdonald3 Feb 20, 2024
3ae1e06
refactor, fix
lucasmcdonald3 Feb 20, 2024
2b5fc72
refactor, fix
lucasmcdonald3 Feb 20, 2024
a940dc5
refactor, fix
lucasmcdonald3 Feb 20, 2024
708ab5e
it works locally but fails on gha
lucasmcdonald3 Feb 20, 2024
ffd295c
it works locally but fails on gha
lucasmcdonald3 Feb 20, 2024
1ba175c
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
fa175ba
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
2f90a97
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
df9215f
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
b57e4a3
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
9d7ec6d
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
2cbc845
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
def946d
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
dff6ac0
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
78f0b0f
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
20a469e
it works locally but fails on gha
lucasmcdonald3 Feb 21, 2024
66859a7
fix tests
lucasmcdonald3 Feb 21, 2024
bf8f67c
cleanup
lucasmcdonald3 Feb 21, 2024
b24be11
re-enable test
lucasmcdonald3 Feb 21, 2024
acba1b0
re-enable test
lucasmcdonald3 Feb 21, 2024
42b7b74
longpaths
lucasmcdonald3 Feb 21, 2024
f226e7e
longpaths
lucasmcdonald3 Feb 21, 2024
aa2f80a
debug windows fail
lucasmcdonald3 Feb 21, 2024
bc002b6
debug windows fail
lucasmcdonald3 Feb 21, 2024
8dd0303
debug windows fail
lucasmcdonald3 Feb 21, 2024
1e9db3b
debug windows fail
lucasmcdonald3 Feb 21, 2024
74d4e66
disable windows until pythonpath
lucasmcdonald3 Feb 21, 2024
1bb23e8
expand testing
lucasmcdonald3 Feb 21, 2024
1ee69ce
expand testing
lucasmcdonald3 Feb 21, 2024
b33f2f7
expand testing
lucasmcdonald3 Feb 21, 2024
c582888
expand testing
lucasmcdonald3 Feb 21, 2024
5ae44f5
expand testing
lucasmcdonald3 Feb 21, 2024
cb7e3d1
cleanup
lucasmcdonald3 Feb 21, 2024
b026b53
cleanup
lucasmcdonald3 Feb 21, 2024
50afa3a
cleanup
lucasmcdonald3 Feb 21, 2024
1c612a0
cleanup
lucasmcdonald3 Feb 21, 2024
bcdb4ba
add missing file
lucasmcdonald3 Feb 21, 2024
41fe2f9
add missing file
lucasmcdonald3 Feb 21, 2024
1ba857e
add missing file
lucasmcdonald3 Feb 21, 2024
74bfe12
cleanup
lucasmcdonald3 Feb 21, 2024
b3b9a0f
refactor
lucasmcdonald3 Feb 22, 2024
a594125
refactor
lucasmcdonald3 Feb 22, 2024
fdd2eda
unit tests
lucasmcdonald3 Feb 23, 2024
0138f22
unit tests
lucasmcdonald3 Feb 23, 2024
f213e19
upgrade image
lucasmcdonald3 Feb 23, 2024
d55f296
refactor tests
lucasmcdonald3 Feb 23, 2024
5ec4668
refactor tests
lucasmcdonald3 Feb 23, 2024
61ba4de
refactor tests
lucasmcdonald3 Feb 23, 2024
95c5be6
refactor tests
lucasmcdonald3 Feb 23, 2024
9566873
refactor tests
lucasmcdonald3 Feb 23, 2024
6642083
fix cov
lucasmcdonald3 Feb 23, 2024
51d2804
fix cov
lucasmcdonald3 Feb 23, 2024
51e5db5
fix cov
lucasmcdonald3 Feb 23, 2024
e235461
fix cov
lucasmcdonald3 Feb 23, 2024
e7c745f
fix tests
lucasmcdonald3 Feb 23, 2024
fee4f36
test cleanup
lucasmcdonald3 Feb 24, 2024
ac6471a
test cleanup
lucasmcdonald3 Feb 24, 2024
a5ebc19
isort
lucasmcdonald3 Feb 24, 2024
21f3614
fixes
lucasmcdonald3 Feb 24, 2024
22eabb6
fix
lucasmcdonald3 Feb 24, 2024
ac0ceb3
fix
lucasmcdonald3 Feb 24, 2024
2fd8858
oops
lucasmcdonald3 Feb 24, 2024
51c6a9c
revert
lucasmcdonald3 Feb 24, 2024
800f9de
revert
lucasmcdonald3 Feb 24, 2024
ebcb759
fix
lucasmcdonald3 Feb 24, 2024
cf26ca3
fix
lucasmcdonald3 Feb 24, 2024
7f27ebd
fix
lucasmcdonald3 Feb 24, 2024
00f4721
fix
lucasmcdonald3 Feb 24, 2024
018b93f
fix
lucasmcdonald3 Feb 24, 2024
d413b65
fix
lucasmcdonald3 Feb 24, 2024
c4ca658
copyright
lucasmcdonald3 Feb 24, 2024
d99b666
more unit tests
lucasmcdonald3 Feb 26, 2024
49cb7c8
more unit tests
lucasmcdonald3 Feb 26, 2024
705113a
more unit tests
lucasmcdonald3 Feb 26, 2024
f76d7f9
more unit tests
lucasmcdonald3 Feb 26, 2024
0da2a4f
more unit tests
lucasmcdonald3 Feb 26, 2024
0040b2c
cleanup
lucasmcdonald3 Feb 26, 2024
9131433
cleanup
lucasmcdonald3 Feb 26, 2024
e6826eb
poc impl
lucasmcdonald3 Feb 28, 2024
a9fa1a5
passing
lucasmcdonald3 Feb 28, 2024
4eeb858
cleanup
lucasmcdonald3 Feb 28, 2024
21a8c93
protect
lucasmcdonald3 Feb 29, 2024
de870b8
ex
lucasmcdonald3 Feb 29, 2024
eedf1a3
changes
lucasmcdonald3 Feb 29, 2024
1db73eb
changes
lucasmcdonald3 Feb 29, 2024
8415c2c
cleanup
lucasmcdonald3 Feb 29, 2024
20bdaff
cleanup
lucasmcdonald3 Feb 29, 2024
6bf6094
cleanup
lucasmcdonald3 Feb 29, 2024
febe6db
cleanup
lucasmcdonald3 Feb 29, 2024
dc8abca
cleanup
lucasmcdonald3 Feb 29, 2024
8ff46f4
cleanup
lucasmcdonald3 Feb 29, 2024
aba7ccc
cleanup
lucasmcdonald3 Feb 29, 2024
40fecc0
all message format versions
lucasmcdonald3 Feb 29, 2024
52043b9
sync upstream
lucasmcdonald3 Feb 29, 2024
14c287d
Merge
lucasmcdonald3 Mar 13, 2024
2d26009
Merge branch 'lucmcdon/mpl' into lucmcdon/mpl-requiredec
lucasmcdonald3 Mar 13, 2024
7374fcb
unit tests
lucasmcdonald3 Mar 26, 2024
f9d60a8
lint
lucasmcdonald3 Mar 26, 2024
16725f8
lint
lucasmcdonald3 Mar 26, 2024
1706db2
lint
lucasmcdonald3 Mar 26, 2024
06e0842
lint
lucasmcdonald3 Mar 26, 2024
5ad8e3a
Update examples/src/keyrings/hierarchical_keyring.py
lucasmcdonald3 Apr 15, 2024
280e038
Update examples/src/keyrings/hierarchical_keyring.py
lucasmcdonald3 Apr 16, 2024
437b81d
chore: kms rsa keyring example
RitvikKapila Apr 26, 2024
5bf8d2b
adding more keyrings
RitvikKapila Apr 29, 2024
41f901b
chore: updated multi, discovery and discovery multi keyrings
RitvikKapila Apr 29, 2024
731c698
chore: fixed naming in test_i_multi_keyring_example.py, added aws_kms…
RitvikKapila Apr 29, 2024
8bd9383
fix: updated aws_kms_rsa_keyring
RitvikKapila Apr 30, 2024
f7a0a7a
fix
RitvikKapila Apr 30, 2024
c124ebb
Merge branch 'mpl-reviewed' into rkapila/multi-discovery-kmsrsa-keyrings
RitvikKapila May 1, 2024
86845ea
fix
RitvikKapila May 1, 2024
ca8943b
fix
RitvikKapila May 1, 2024
c56e924
fix(-)
RitvikKapila May 1, 2024
3c7292b
fix
RitvikKapila May 1, 2024
7cb5864
update
RitvikKapila May 1, 2024
d2b79c9
fix cb
lucasmcdonald3 May 1, 2024
324f683
fix
lucasmcdonald3 May 1, 2024
8c9d4b1
fix: unit tests for _native_algorithm_id_to_mpl_algorithm_id
RitvikKapila May 2, 2024
3c41753
fixed comments
RitvikKapila May 2, 2024
036662f
fix
RitvikKapila May 2, 2024
cbf72ff
Update aws_kms_rsa_keyring_example.py
RitvikKapila May 2, 2024
41e40f3
fix
RitvikKapila May 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions examples/src/keyrings/aws_kms_discovery_keyring_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# 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.

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
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,
aws_account_id: str,
aws_region: str
):
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Keyring.

Usage: encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_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
:param aws_account_id: AWS Account ID to use in the discovery filter
:type aws_account_id: string
:param aws_region: AWS Region to use for the kms client
:type aws_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 a boto3 client for KMS.
kms_client = boto3.client('kms', region_name=aws_region)

# 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 with 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 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=[aws_account_id],
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 this assumes Account ID used here ('888888888888') is different than the one used
# during encryption
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
173 changes: 173 additions & 0 deletions examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# 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.

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,
aws_account_id: str,
aws_regions: list[str]
):
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Multi Keyring.

Usage: encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_id, aws_regions)
: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
:param aws_account_id: AWS Account ID to use in the discovery filter
:type aws_account_id: string
:param aws_regions: List of AWS Regions to use for creating the discovery multi keyring
:type aws_regions: list[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 with 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=aws_regions,
discovery_filter=DiscoveryFilter(
account_ids=[aws_account_id],
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
Loading
Loading