Skip to content

Commit 4c41f05

Browse files
committed
chore(performance_tests): added hierarchy keyring and caching cmm tests
1 parent ebbc26b commit 4c41f05

File tree

12 files changed

+617
-0
lines changed

12 files changed

+617
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Performance tests for the hierarchy keyring."""
4+
5+
# noqa pylint: disable=wrong-import-order
6+
from typing import Dict
7+
8+
import aws_encryption_sdk
9+
import boto3
10+
from aws_cryptographic_materialproviders.keystore import KeyStore
11+
from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig
12+
from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn
13+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
14+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
15+
from aws_cryptographic_materialproviders.mpl.models import (
16+
CacheTypeDefault,
17+
CreateAwsKmsHierarchicalKeyringInput,
18+
DefaultCache,
19+
GetBranchKeyIdInput,
20+
GetBranchKeyIdOutput,
21+
)
22+
from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier, IKeyring
23+
24+
from ..utils.util import PerfTestUtils
25+
26+
27+
class ExampleBranchKeyIdSupplier(IBranchKeyIdSupplier):
28+
"""Example implementation of a branch key ID supplier."""
29+
30+
branch_key_id_for_tenant_a: str
31+
branch_key_id_for_tenant_b: str
32+
33+
def __init__(self, tenant_1_id, tenant_2_id):
34+
"""Example constructor for a branch key ID supplier."""
35+
self.branch_key_id_for_tenant_a = tenant_1_id
36+
self.branch_key_id_for_tenant_b = tenant_2_id
37+
38+
def get_branch_key_id(
39+
self,
40+
param: GetBranchKeyIdInput
41+
) -> GetBranchKeyIdOutput:
42+
"""Returns branch key ID from the tenant ID in input's encryption context."""
43+
encryption_context: Dict[str, str] = param.encryption_context
44+
45+
if b"tenant" not in encryption_context:
46+
raise ValueError("EncryptionContext invalid, does not contain expected tenant key value pair.")
47+
48+
tenant_key_id: str = encryption_context.get(b"tenant")
49+
branch_key_id: str
50+
51+
if tenant_key_id == b"TenantA":
52+
branch_key_id = self.branch_key_id_for_tenant_a
53+
elif tenant_key_id == b"TenantB":
54+
branch_key_id = self.branch_key_id_for_tenant_b
55+
else:
56+
raise ValueError(f"Item does not contain valid tenant ID: {tenant_key_id=}")
57+
58+
return GetBranchKeyIdOutput(branch_key_id=branch_key_id)
59+
60+
61+
def create_keyring(
62+
key_store_table_name: str,
63+
logical_key_store_name: str,
64+
kms_key_id: str
65+
):
66+
"""Demonstrate how to create a hierarchy keyring.
67+
68+
Usage: create_keyring(key_store_table_name, logical_key_store_name, kms_key_id)
69+
:param key_store_table_name: Name of the KeyStore DynamoDB table.
70+
:type key_store_table_name: string
71+
:param logical_key_store_name: Logical name of the KeyStore.
72+
:type logical_key_store_name: string
73+
:param kms_key_id: KMS Key identifier for the KMS key you want to use.
74+
:type kms_key_id: string
75+
76+
For more information on KMS Key identifiers, see
77+
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
78+
"""
79+
# Create boto3 clients for DynamoDB and KMS.
80+
ddb_client = boto3.client('dynamodb', region_name="us-west-2")
81+
kms_client = boto3.client('kms', region_name="us-west-2")
82+
83+
# Configure your KeyStore resource.
84+
# This SHOULD be the same configuration that you used
85+
# to initially create and populate your KeyStore.
86+
keystore: KeyStore = KeyStore(
87+
config=KeyStoreConfig(
88+
ddb_client=ddb_client,
89+
ddb_table_name=key_store_table_name,
90+
logical_key_store_name=logical_key_store_name,
91+
kms_client=kms_client,
92+
kms_configuration=KMSConfigurationKmsKeyArn(
93+
value=kms_key_id
94+
),
95+
)
96+
)
97+
98+
# Call CreateKey to create two new active branch keys
99+
branch_key_id_a: str = PerfTestUtils.DEFAULT_BRANCH_KEY_ID_A
100+
branch_key_id_b: str = PerfTestUtils.DEFAULT_BRANCH_KEY_ID_B
101+
102+
# Create a branch key supplier that maps the branch key id to a more readable format
103+
branch_key_id_supplier: IBranchKeyIdSupplier = ExampleBranchKeyIdSupplier(
104+
tenant_1_id=branch_key_id_a,
105+
tenant_2_id=branch_key_id_b,
106+
)
107+
108+
# Create the Hierarchical Keyring.
109+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
110+
config=MaterialProvidersConfig()
111+
)
112+
113+
keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput(
114+
key_store=keystore,
115+
branch_key_id_supplier=branch_key_id_supplier,
116+
ttl_seconds=600,
117+
cache=CacheTypeDefault(
118+
value=DefaultCache(
119+
entry_capacity=100
120+
)
121+
),
122+
)
123+
124+
keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring(
125+
input=keyring_input
126+
)
127+
128+
return keyring
129+
130+
131+
def encrypt_using_keyring(
132+
plaintext_data: bytes,
133+
keyring: IKeyring
134+
):
135+
"""Demonstrate how to encrypt plaintext data using a hierarchy keyring.
136+
137+
Usage: encrypt_using_keyring(plaintext_data, keyring)
138+
:param plaintext_data: plaintext data you want to encrypt
139+
:type: bytes
140+
:param keyring: Keyring to use for encryption.
141+
:type keyring: IKeyring
142+
"""
143+
client = aws_encryption_sdk.EncryptionSDKClient()
144+
145+
ciphertext_data, _ = client.encrypt(
146+
source=plaintext_data,
147+
keyring=keyring,
148+
encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT
149+
)
150+
151+
return ciphertext_data
152+
153+
154+
def decrypt_using_keyring(
155+
ciphertext_data: bytes,
156+
keyring: IKeyring
157+
):
158+
"""Demonstrate how to decrypt ciphertext data using a hierarchy keyring.
159+
160+
Usage: decrypt_using_keyring(ciphertext_data, keyring)
161+
:param ciphertext_data: ciphertext data you want to decrypt
162+
:type: bytes
163+
:param keyring: Keyring to use for decryption.
164+
:type keyring: IKeyring
165+
"""
166+
client = aws_encryption_sdk.EncryptionSDKClient()
167+
168+
decrypted_plaintext_data, _ = client.decrypt(
169+
source=ciphertext_data,
170+
keyring=keyring,
171+
encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT
172+
)
173+
174+
return decrypted_plaintext_data
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Performance tests for the Caching Cryptographic Materials Manager (CMM)."""
4+
5+
import aws_encryption_sdk
6+
7+
8+
def create_cmm(
9+
kms_key_id: str,
10+
max_age_in_cache: float,
11+
cache_capacity: int
12+
):
13+
"""Demonstrate how to create a Caching CMM.
14+
15+
Usage: create_cmm(kms_key_id, max_age_in_cache, cache_capacity)
16+
:param kms_key_id: Amazon Resource Name (ARN) of the KMS customer master key
17+
:type kms_key_id: str
18+
:param max_age_in_cache: Maximum time in seconds that a cached entry can be used
19+
:type max_age_in_cache: float
20+
:param cache_capacity: Maximum number of entries to retain in cache at once
21+
:type cache_capacity: int
22+
"""
23+
# Security thresholds
24+
# Max messages (or max bytes per) data key are optional
25+
max_entry_messages = 100
26+
27+
# Create a master key provider for the KMS customer master key (CMK)
28+
key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_id])
29+
30+
# Create a local cache
31+
cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity)
32+
33+
# Create a caching CMM
34+
caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager(
35+
master_key_provider=key_provider,
36+
cache=cache,
37+
max_age=max_age_in_cache,
38+
max_messages_encrypted=max_entry_messages,
39+
)
40+
41+
return caching_cmm
42+
43+
44+
def encrypt_using_cmm(
45+
plaintext_data: bytes,
46+
caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
47+
):
48+
"""Demonstrate how to encrypt plaintext data using a Caching CMM.
49+
50+
Usage: encrypt_using_cmm(plaintext_data, caching_cmm)
51+
:param plaintext_data: plaintext data you want to encrypt
52+
:type: bytes
53+
:param caching_cmm: Crypto Materials Manager to use for encryption.
54+
:type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
55+
"""
56+
client = aws_encryption_sdk.EncryptionSDKClient()
57+
58+
ciphertext_data, _ = client.encrypt(
59+
source=plaintext_data,
60+
materials_manager=caching_cmm
61+
)
62+
63+
return ciphertext_data
64+
65+
66+
def decrypt_using_cmm(
67+
ciphertext_data: bytes,
68+
caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
69+
):
70+
"""Demonstrate how to decrypt ciphertext data using a Caching CMM.
71+
72+
Usage: decrypt_using_cmm(ciphertext_data, caching_cmm)
73+
:param ciphertext_data: ciphertext data you want to decrypt
74+
:type: bytes
75+
:param caching_cmm: Crypto Materials Manager to use for encryption.
76+
:type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
77+
"""
78+
client = aws_encryption_sdk.EncryptionSDKClient()
79+
80+
decrypted_plaintext_data, _ = client.decrypt(
81+
source=ciphertext_data,
82+
materials_manager=caching_cmm
83+
)
84+
85+
return decrypted_plaintext_data

0 commit comments

Comments
 (0)