Skip to content

Commit 750bb68

Browse files
authored
chore: Added KMS keyring example (#659)
1 parent 91d06ae commit 750bb68

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""
4+
This example sets up the KMS Keyring
5+
6+
The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and
7+
decrypt data keys. This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA
8+
with an encryption context. This example also includes some sanity checks for demonstration:
9+
1. Ciphertext and plaintext data are not the same
10+
2. Encryption context is correct in the decrypted message header
11+
3. Decrypted plaintext value matches EXAMPLE_DATA
12+
These sanity checks are for demonstration in the example only. You do not need these in your code.
13+
14+
AWS KMS keyrings can be used independently or in a multi-keyring with other keyrings
15+
of the same or a different type.
16+
17+
For more information on how to use KMS keyrings, see
18+
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html
19+
"""
20+
import sys
21+
22+
import boto3
23+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
24+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
25+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
26+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
27+
from typing import Dict
28+
29+
import aws_encryption_sdk
30+
from aws_encryption_sdk import CommitmentPolicy
31+
32+
# TODO-MPL: Remove this as part of removing PYTHONPATH hacks.
33+
MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1])
34+
35+
sys.path.append(MODULE_ROOT_DIR)
36+
37+
EXAMPLE_DATA: bytes = b"Hello World"
38+
39+
40+
def encrypt_and_decrypt_with_keyring(
41+
kms_key_id: str
42+
):
43+
"""Demonstrate an encrypt/decrypt cycle using an AWS KMS keyring.
44+
45+
Usage: encrypt_and_decrypt_with_keyring(kms_key_id)
46+
:param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and
47+
decryption of your data keys.
48+
:type kms_key_id: string
49+
50+
For more information on KMS Key identifiers, see
51+
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
52+
"""
53+
# 1. Instantiate the encryption SDK client.
54+
# This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
55+
# which enforces that this client only encrypts using committing algorithm suites and enforces
56+
# that this client will only decrypt encrypted messages that were created with a committing
57+
# algorithm suite.
58+
# This is the default commitment policy if you were to build the client as
59+
# `client = aws_encryption_sdk.EncryptionSDKClient()`.
60+
client = aws_encryption_sdk.EncryptionSDKClient(
61+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
62+
)
63+
64+
# 2. Create a boto3 client for KMS.
65+
kms_client = boto3.client('kms', region_name="us-west-2")
66+
67+
# 3. Create encryption context.
68+
# Remember that your encryption context is NOT SECRET.
69+
# For more information, see
70+
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
71+
encryption_context: Dict[str, str] = {
72+
"encryption": "context",
73+
"is not": "secret",
74+
"but adds": "useful metadata",
75+
"that can help you": "be confident that",
76+
"the data you are handling": "is what you think it is",
77+
}
78+
79+
# 4. Create a KMS keyring
80+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
81+
config=MaterialProvidersConfig()
82+
)
83+
84+
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
85+
kms_key_id=kms_key_id,
86+
kms_client=kms_client
87+
)
88+
89+
kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
90+
input=keyring_input
91+
)
92+
93+
# 5. Encrypt the data with the encryptionContext.
94+
ciphertext, _ = client.encrypt(
95+
source=EXAMPLE_DATA,
96+
keyring=kms_keyring,
97+
encryption_context=encryption_context
98+
)
99+
100+
# 6. Demonstrate that the ciphertext and plaintext are different.
101+
# (This is an example for demonstration; you do not need to do this in your own code.)
102+
assert ciphertext != EXAMPLE_DATA, \
103+
"Ciphertext and plaintext data are the same. Invalid encryption"
104+
105+
# 7. Decrypt your encrypted data using the same keyring you used on encrypt.
106+
plaintext_bytes, dec_header = client.decrypt(
107+
source=ciphertext,
108+
keyring=kms_keyring
109+
)
110+
111+
# 8. Demonstrate that the encryption context is correct in the decrypted message header
112+
# (This is an example for demonstration; you do not need to do this in your own code.)
113+
for k, v in encryption_context.items():
114+
assert v == dec_header.encryption_context[k], \
115+
"Encryption context does not match expected values"
116+
117+
# 9. Demonstrate that the decrypted plaintext is identical to the original plaintext.
118+
# (This is an example for demonstration; you do not need to do this in your own code.)
119+
assert plaintext_bytes == EXAMPLE_DATA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for the AWS KMS keyring example."""
4+
import pytest
5+
6+
from ...src.keyrings.aws_kms_keyring_example import encrypt_and_decrypt_with_keyring
7+
8+
pytestmark = [pytest.mark.examples]
9+
10+
11+
def test_encrypt_and_decrypt_with_keyring():
12+
"""Test function for encrypt and decrypt using the AWS KMS Keyring example."""
13+
kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"
14+
encrypt_and_decrypt_with_keyring(kms_key_id)

examples/test/keyrings/test_i_hierarchical_keyring.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111
def test_encrypt_and_decrypt_with_keyring():
12+
"""Test function for encrypt and decrypt using the AWS KMS Hierarchical Keyring example."""
1213
key_store_table_name = "KeyStoreDdbTable"
13-
key_arn = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"
14-
encrypt_and_decrypt_with_keyring(key_store_table_name, key_store_table_name, key_arn)
14+
kms_key_id = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"
15+
encrypt_and_decrypt_with_keyring(key_store_table_name, key_store_table_name, kms_key_id)

0 commit comments

Comments
 (0)