Skip to content

Commit aaadba3

Browse files
committed
linter
1 parent 1bdc2e2 commit aaadba3

File tree

4 files changed

+84
-102
lines changed

4 files changed

+84
-102
lines changed
Lines changed: 43 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
"""
4-
This example sets up an MRK multi-keyring and an MRK discovery
5-
multi-keyring using a custom client supplier.
6-
7-
A custom client supplier grants users access to more granular
8-
configuration aspects of their authentication details and KMS
9-
client. In this example, we create a simple custom client supplier
10-
that authenticates with a different IAM role based on the
11-
region of the KMS key.
12-
13-
This example creates a MRK multi-keyring configured with a custom
14-
client supplier using a single MRK and puts an encrypted item to the
15-
table. Then, it creates a MRK discovery multi-keyring to decrypt the item
16-
and retrieves the item from the table.
17-
18-
Running this example requires access to the DDB Table whose name
19-
is provided in CLI arguments.
20-
This table must be configured with the following
21-
primary key configuration:
4+
Example demonstrating Dynamodb Encryption using a custom client supplier.
5+
6+
A custom client supplier grants users access to more granular configuration aspects
7+
of their authentication details and KMS client. The example creates a simple custom
8+
client supplier that authenticates with a different IAM role based on the region
9+
of the KMS key.
10+
11+
Creates a MRK multi-keyring configured with a custom client supplier using a single
12+
MRK and puts an encrypted item to the table. Then, creates a MRK discovery
13+
multi-keyring to decrypt the item and retrieves the item from the table.
14+
15+
Running this example requires access to the DDB Table whose name is provided in
16+
CLI arguments. This table must be configured with the following primary key
17+
configuration:
2218
- Partition key is named "partition_key" with type (S)
2319
- Sort key is named "sort_key" with type (N)
2420
"""
@@ -29,11 +25,10 @@
2925
from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders
3026
from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig
3127
from aws_cryptographic_material_providers.mpl.models import (
32-
CreateAwsKmsMrkMultiKeyringInput,
3328
CreateAwsKmsMrkDiscoveryMultiKeyringInput,
29+
CreateAwsKmsMrkMultiKeyringInput,
3430
DiscoveryFilter,
3531
)
36-
from aws_cryptographic_material_providers.mpl.references import IKeyring
3732
from aws_dbesdk_dynamodb.encrypted.client import EncryptedClient
3833
from aws_dbesdk_dynamodb.structures.dynamodb import (
3934
DynamoDbTableEncryptionConfig,
@@ -46,15 +41,12 @@
4641
from .regional_role_client_supplier import RegionalRoleClientSupplier
4742

4843

49-
def client_supplier_example(
50-
ddb_table_name: str,
51-
key_arn: str,
52-
account_ids: List[str],
53-
regions: List[str]
54-
) -> None:
44+
def client_supplier_example(ddb_table_name: str, key_arn: str, account_ids: List[str], regions: List[str]) -> None:
5545
"""
56-
Demonstrate how to use a custom client supplier with AWS KMS MRK multi-keyring
57-
and AWS KMS MRK discovery multi-keyring.
46+
Demonstrate using custom client supplier with AWS KMS MRK keyrings.
47+
48+
Shows how to use a custom client supplier with AWS KMS MRK multi-keyring and AWS
49+
KMS MRK discovery multi-keyring.
5850
5951
:param ddb_table_name: The name of the DynamoDB table
6052
:param key_arn: The ARN of the AWS KMS key
@@ -69,14 +61,14 @@ def client_supplier_example(
6961
# in a region in the regions list, and the client
7062
# must have the correct permissions to access the replica.
7163
mat_prov = AwsCryptographicMaterialProviders(config=MaterialProvidersConfig())
72-
64+
7365
# Create the multi-keyring using our custom client supplier
7466
# defined in the RegionalRoleClientSupplier class in this directory.
7567
create_aws_kms_mrk_multi_keyring_input = CreateAwsKmsMrkMultiKeyringInput(
7668
# Note: RegionalRoleClientSupplier will internally use the keyArn's region
7769
# to retrieve the correct IAM role.
7870
client_supplier=RegionalRoleClientSupplier(),
79-
generator=key_arn
71+
generator=key_arn,
8072
)
8173
mrk_keyring_with_client_supplier = mat_prov.create_aws_kms_mrk_multi_keyring(
8274
input=create_aws_kms_mrk_multi_keyring_input
@@ -91,7 +83,7 @@ def client_supplier_example(
9183
attribute_actions_on_encrypt = {
9284
"partition_key": CryptoAction.SIGN_ONLY, # Our partition attribute must be SIGN_ONLY
9385
"sort_key": CryptoAction.SIGN_ONLY, # Our sort attribute must be SIGN_ONLY
94-
"sensitive_data": CryptoAction.ENCRYPT_AND_SIGN
86+
"sensitive_data": CryptoAction.ENCRYPT_AND_SIGN,
9587
}
9688

9789
# 3. Configure which attributes we expect to be included in the signature
@@ -131,18 +123,15 @@ def client_supplier_example(
131123
sort_key_name="sort_key",
132124
attribute_actions_on_encrypt=attribute_actions_on_encrypt,
133125
keyring=mrk_keyring_with_client_supplier,
134-
allowed_unsigned_attribute_prefix=unsign_attr_prefix
126+
allowed_unsigned_attribute_prefix=unsign_attr_prefix,
135127
)
136128

137129
table_configs = {ddb_table_name: table_config}
138130
tables_config = DynamoDbTablesEncryptionConfig(table_encryption_configs=table_configs)
139131

140132
# 5. Create the EncryptedClient
141-
ddb_client = boto3.client('dynamodb')
142-
encrypted_ddb_client = EncryptedClient(
143-
client=ddb_client,
144-
encryption_config=tables_config
145-
)
133+
ddb_client = boto3.client("dynamodb")
134+
encrypted_ddb_client = EncryptedClient(client=ddb_client, encryption_config=tables_config)
146135

147136
# 6. Put an item into our table using the above client.
148137
# Before the item gets sent to DynamoDb, it will be encrypted
@@ -153,33 +142,24 @@ def client_supplier_example(
153142
item = {
154143
"partition_key": {"S": "clientSupplierItem"},
155144
"sort_key": {"N": "0"},
156-
"sensitive_data": {"S": "encrypt and sign me!"}
145+
"sensitive_data": {"S": "encrypt and sign me!"},
157146
}
158147

159-
put_response = encrypted_ddb_client.put_item(
160-
TableName=ddb_table_name,
161-
Item=item
162-
)
148+
put_response = encrypted_ddb_client.put_item(TableName=ddb_table_name, Item=item)
163149

164150
# Demonstrate that PutItem succeeded
165-
assert put_response['ResponseMetadata']['HTTPStatusCode'] == 200
151+
assert put_response["ResponseMetadata"]["HTTPStatusCode"] == 200
166152

167153
# 7. Get the item back from our table using the same keyring.
168154
# The client will decrypt the item client-side using the MRK
169155
# and return the original item.
170-
key_to_get = {
171-
"partition_key": {"S": "clientSupplierItem"},
172-
"sort_key": {"N": "0"}
173-
}
156+
key_to_get = {"partition_key": {"S": "clientSupplierItem"}, "sort_key": {"N": "0"}}
174157

175-
get_response = encrypted_ddb_client.get_item(
176-
TableName=ddb_table_name,
177-
Key=key_to_get
178-
)
158+
get_response = encrypted_ddb_client.get_item(TableName=ddb_table_name, Key=key_to_get)
179159

180160
# Demonstrate that GetItem succeeded and returned the decrypted item
181-
assert get_response['ResponseMetadata']['HTTPStatusCode'] == 200
182-
returned_item = get_response['Item']
161+
assert get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
162+
returned_item = get_response["Item"]
183163
assert returned_item["sensitive_data"]["S"] == "encrypt and sign me!"
184164

185165
# 8. Create a MRK discovery multi-keyring with a custom client supplier.
@@ -190,17 +170,12 @@ def client_supplier_example(
190170
# keyrings will use that client supplier configuration.
191171
# In our tests, we make `key_arn` an MRK with a replica, and
192172
# provide only the replica region in our discovery filter.
193-
discovery_filter = DiscoveryFilter(
194-
partition="aws",
195-
account_ids=account_ids
196-
)
173+
discovery_filter = DiscoveryFilter(partition="aws", account_ids=account_ids)
197174

198175
mrk_discovery_client_supplier_input = CreateAwsKmsMrkDiscoveryMultiKeyringInput(
199-
client_supplier=RegionalRoleClientSupplier(),
200-
discovery_filter=discovery_filter,
201-
regions=regions
176+
client_supplier=RegionalRoleClientSupplier(), discovery_filter=discovery_filter, regions=regions
202177
)
203-
178+
204179
mrk_discovery_client_supplier_keyring = mat_prov.create_aws_kms_mrk_discovery_multi_keyring(
205180
input=mrk_discovery_client_supplier_input
206181
)
@@ -214,7 +189,7 @@ def client_supplier_example(
214189
attribute_actions_on_encrypt=attribute_actions_on_encrypt,
215190
# Provide discovery keyring here
216191
keyring=mrk_discovery_client_supplier_keyring,
217-
allowed_unsigned_attribute_prefix=unsign_attr_prefix
192+
allowed_unsigned_attribute_prefix=unsign_attr_prefix,
218193
)
219194

220195
replica_key_tables_config = {ddb_table_name: replica_key_table_config}
@@ -223,8 +198,7 @@ def client_supplier_example(
223198
)
224199

225200
replica_key_encrypted_client = EncryptedClient(
226-
client=ddb_client,
227-
encryption_config=replica_key_tables_encryption_config
201+
client=ddb_client, encryption_config=replica_key_tables_encryption_config
228202
)
229203

230204
# 10. Get the item back from our table using the discovery keyring client.
@@ -235,17 +209,13 @@ def client_supplier_example(
235209
# which uses different IAM roles based on the key region,
236210
# the discovery keyring will use a particular IAM role to decrypt
237211
# based on the region of the KMS key it uses to decrypt.
238-
replica_key_key_to_get = {
239-
"partition_key": {"S": "awsKmsMrkMultiKeyringItem"},
240-
"sort_key": {"N": "0"}
241-
}
212+
replica_key_key_to_get = {"partition_key": {"S": "awsKmsMrkMultiKeyringItem"}, "sort_key": {"N": "0"}}
242213

243214
replica_key_get_response = replica_key_encrypted_client.get_item(
244-
TableName=ddb_table_name,
245-
Key=replica_key_key_to_get
215+
TableName=ddb_table_name, Key=replica_key_key_to_get
246216
)
247217

248218
# Demonstrate that GetItem succeeded and returned the decrypted item
249-
assert replica_key_get_response['ResponseMetadata']['HTTPStatusCode'] == 200
250-
replica_key_returned_item = replica_key_get_response['Item']
251-
assert replica_key_returned_item["sensitive_data"]["S"] == "encrypt and sign me!"
219+
assert replica_key_get_response["ResponseMetadata"]["HTTPStatusCode"] == 200
220+
replica_key_returned_item = replica_key_get_response["Item"]
221+
assert replica_key_returned_item["sensitive_data"]["S"] == "encrypt and sign me!"
Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
"""
4-
Example class demonstrating an implementation of a custom client supplier.
5-
This particular implementation will create KMS clients with different IAM roles,
6-
depending on the region passed.
4+
Demonstrates implementing a custom client supplier.
5+
6+
Creates KMS clients with different IAM roles depending on the region passed.
77
"""
88

9-
import boto3
109
import logging
11-
from botocore.exceptions import ClientError
12-
from aws_cryptographic_material_providers.mpl.references import ClientSupplier
10+
11+
import boto3
1312
from aws_cryptographic_material_providers.mpl.models import GetClientInput
13+
from aws_cryptographic_material_providers.mpl.references import ClientSupplier
14+
from botocore.exceptions import ClientError
1415

1516
from .regional_role_client_supplier_config import RegionalRoleClientSupplierConfig
1617

1718

1819
class RegionalRoleClientSupplier(ClientSupplier):
1920
"""
20-
Custom client supplier that creates KMS clients with different IAM roles
21-
depending on the region passed.
21+
Custom client supplier for region-specific IAM roles.
22+
23+
Creates KMS clients with different IAM roles depending on the region passed.
2224
"""
2325

2426
def __init__(self):
25-
self._sts_client = boto3.client('sts')
27+
"""Initialize the client supplier with STS client and configuration."""
28+
self._sts_client = boto3.client("sts")
2629
self._config = RegionalRoleClientSupplierConfig()
2730
self._logger = logging.getLogger(__name__)
2831

@@ -40,27 +43,27 @@ def get_client(self, input_params: GetClientInput) -> boto3.client:
4043
region = input_params.region
4144
if region not in self._config.region_iam_role_map:
4245
self._logger.warning(f"Missing region in config: {region}. Using default client.")
43-
return boto3.client('kms', region_name=region)
44-
46+
return boto3.client("kms", region_name=region)
47+
4548
role_arn = self._config.region_iam_role_map[region]
46-
49+
4750
try:
4851
# Assume the IAM role for the region
4952
response = self._sts_client.assume_role(
5053
RoleArn=role_arn,
5154
DurationSeconds=900, # 15 minutes is the minimum value
52-
RoleSessionName="Python-Client-Supplier-Example-Session"
55+
RoleSessionName="Python-Client-Supplier-Example-Session",
5356
)
54-
57+
5558
# Create a KMS client with the temporary credentials
5659
return boto3.client(
57-
'kms',
60+
"kms",
5861
region_name=region,
59-
aws_access_key_id=response['Credentials']['AccessKeyId'],
60-
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
61-
aws_session_token=response['Credentials']['SessionToken']
62+
aws_access_key_id=response["Credentials"]["AccessKeyId"],
63+
aws_secret_access_key=response["Credentials"]["SecretAccessKey"],
64+
aws_session_token=response["Credentials"]["SessionToken"],
6265
)
6366
except ClientError as e:
6467
# In test environments, fall back to a standard client
6568
self._logger.warning(f"Failed to assume role: {str(e)}. Falling back to default client.")
66-
return boto3.client('kms', region_name=region)
69+
return boto3.client("kms", region_name=region)
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
"""
4-
Class containing config for the RegionalRoleClientSupplier.
5-
In your own code, this might be hardcoded, or reference
6-
an external source, e.g. environment variables or AWS AppConfig.
4+
Configuration for the RegionalRoleClientSupplier.
5+
6+
Contains hardcoded configuration values for demonstration purposes. In production
7+
code, these values might be loaded from environment variables, AWS AppConfig, or
8+
other external sources.
79
"""
810

911

1012
class RegionalRoleClientSupplierConfig:
13+
"""
14+
Configuration class mapping AWS regions to IAM roles.
15+
16+
Provides a mapping between AWS regions and their corresponding IAM roles for
17+
use in the RegionalRoleClientSupplier. For demonstration purposes, this uses
18+
hardcoded values.
19+
"""
20+
1121
US_EAST_1_IAM_ROLE = "arn:aws:iam::370957321024:role/GitHub-CI-DDBEC-Dafny-Role-only-us-east-1-KMS-keys"
1222
EU_WEST_1_IAM_ROLE = "arn:aws:iam::370957321024:role/GitHub-CI-DDBEC-Dafny-Role-only-eu-west-1-KMS-keys"
1323

1424
def __init__(self):
15-
self.region_iam_role_map = {
16-
"us-east-1": self.US_EAST_1_IAM_ROLE,
17-
"eu-west-1": self.EU_WEST_1_IAM_ROLE
18-
}
25+
"""Initialize the configuration with region to IAM role mapping."""
26+
self.region_iam_role_map = {"us-east-1": self.US_EAST_1_IAM_ROLE, "eu-west-1": self.EU_WEST_1_IAM_ROLE}

Examples/runtimes/python/DynamoDBEncryption/test/client_supplier/test_client_supplier_example.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
"""Test suite for the client supplier example."""
44
import pytest
55

6-
from .. import test_utils
76
from ...src.client_supplier.client_supplier_example import client_supplier_example
7+
from .. import test_utils
88

99
pytestmark = [pytest.mark.examples]
1010

11+
1112
def test_client_supplier_example():
1213
"""Test function for client supplier example."""
1314
accounts = [test_utils.TEST_AWS_ACCOUNT_ID]
@@ -18,5 +19,5 @@ def test_client_supplier_example():
1819
ddb_table_name=test_utils.TEST_DDB_TABLE_NAME,
1920
key_arn=test_utils.TEST_MRK_REPLICA_KEY_ID_US_EAST_1,
2021
account_ids=accounts,
21-
regions=regions
22-
)
22+
regions=regions,
23+
)

0 commit comments

Comments
 (0)