Skip to content

Commit 780ac77

Browse files
author
Lucas McDonald
committed
sync
1 parent c42b1a8 commit 780ac77

File tree

3 files changed

+73
-63
lines changed

3 files changed

+73
-63
lines changed

DynamoDbEncryption/runtimes/python/src/aws_dbesdk_dynamodb/encrypted/client.py

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,25 @@ class EncryptedClient(EncryptedBotoInterface):
4444
drop-in replacement that transparently handles encryption and decryption of items.
4545
4646
The API matches the standard boto3 DynamoDB client interface:
47+
4748
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#client
4849
4950
This class will encrypt/decrypt items for the following operations:
50-
* put_item
51-
* get_item
52-
* query
53-
* scan
54-
* batch_write_item
55-
* batch_get_item
56-
* transact_get_items
57-
* transact_write_items
5851
59-
The update_item operation is not currently supported. Calling this operation will raise NotImplementedError.
52+
* ``put_item``
53+
* ``get_item``
54+
* ``query``
55+
* ``scan``
56+
* ``batch_write_item``
57+
* ``batch_get_item``
58+
* ``transact_get_items``
59+
* ``transact_write_items``
60+
61+
The ``update_item`` operation is not currently supported. Calling this operation will raise ``NotImplementedError``.
6062
6163
Any other operations on this class will defer to the underlying boto3 DynamoDB client's implementation.
6264
63-
EncryptedClient can also return an EncryptedPaginator for transparent decryption of paginated results.
65+
``EncryptedClient`` can also return an ``EncryptedPaginator`` for transparent decryption of paginated results.
6466
"""
6567

6668
_client: botocore.client.BaseClient
@@ -76,15 +78,15 @@ def __init__(
7678
expect_standard_dictionaries: bool | None = False,
7779
):
7880
"""
79-
Create an EncryptedClient object.
81+
Create an ``EncryptedClient`` object.
8082
8183
Args:
8284
client (botocore.client.BaseClient): Initialized boto3 DynamoDB client
8385
encryption_config (DynamoDbTablesEncryptionConfig): Initialized DynamoDbTablesEncryptionConfig
8486
expect_standard_dictionaries (Optional[bool]): Does the underlying boto3 client expect items
8587
to be standard Python dictionaries? This should only be set to True if you are using a
86-
client obtained from a service resource or table resource (ex: `table.meta.client`).
87-
If this is True, EncryptedClient will expect item-like shapes to be
88+
client obtained from a service resource or table resource (ex: ``table.meta.client``).
89+
If this is True, ``EncryptedClient`` will expect item-like shapes to be
8890
standard Python dictionaries (default: False).
8991
9092
"""
@@ -99,15 +101,16 @@ def put_item(self, **kwargs) -> dict[str, Any]:
99101
"""
100102
Put a single item to a table. Encrypts the item before writing to DynamoDB.
101103
102-
The parameters and return value match the boto3 DynamoDB put_item API:
104+
The input and output syntaxes match those for the boto3 DynamoDB ``put_item`` API:
105+
103106
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/put_item.html
104107
105108
Args:
106-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 put_item API parameters.
107-
The "Item" argument will be encrypted locally before being written to DynamoDB.
109+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``put_item`` request syntax.
110+
The value in ``"Item"`` will be encrypted locally before being written to DynamoDB.
108111
109112
Returns:
110-
dict: The response from DynamoDB. This matches the boto3 put_item API response.
113+
dict: The response from DynamoDB. This matches the boto3 ``put_item`` response syntax.
111114
112115
"""
113116
return self._client_operation_logic(
@@ -127,15 +130,16 @@ def get_item(self, **kwargs) -> dict[str, Any]:
127130
"""
128131
Get a single item from a table. Decrypts the item after reading from DynamoDB.
129132
130-
The parameters and return value match the boto3 DynamoDB get_item API:
133+
The input and output syntaxes match those for the boto3 DynamoDB ``get_item`` API:
134+
131135
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/get_item.html
132136
133137
Args:
134-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 get_item API parameters.
138+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``get_item`` request syntax.
135139
136140
Returns:
137-
dict: The response from DynamoDB. This matches the boto3 get_item API response.
138-
The "Item" field will be decrypted locally after being read from DynamoDB.
141+
dict: The response from DynamoDB. This matches the boto3 ``get_item`` response syntax.
142+
The value in ``"Item"`` field be decrypted locally after being read from DynamoDB.
139143
140144
"""
141145
return self._client_operation_logic(
@@ -156,6 +160,7 @@ def query(self, **kwargs) -> dict[str, Any]:
156160
Query items from a table or index. Decrypts any returned items.
157161
158162
The parameters and return value match the boto3 DynamoDB query API:
163+
159164
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/query.html
160165
161166
Args:
@@ -183,15 +188,16 @@ def scan(self, **kwargs) -> dict[str, Any]:
183188
"""
184189
Scan an entire table or index. Decrypts any returned items.
185190
186-
The parameters and return value match the boto3 DynamoDB scan API:
191+
The input and output syntaxes match those for the boto3 DynamoDB ``scan`` API:
192+
187193
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/scan.html
188194
189195
Args:
190-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 scan API parameters.
196+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``scan`` request syntax.
191197
192198
Returns:
193-
dict: The response from DynamoDB. This matches the boto3 scan API response.
194-
The "Items" field will be decrypted locally after being read from DynamoDB.
199+
dict: The response from DynamoDB. This matches the boto3 ``scan`` response syntax.
200+
The values in ``"Items"`` will be decrypted locally after being read from DynamoDB.
195201
196202
"""
197203
return self._client_operation_logic(
@@ -213,16 +219,17 @@ def batch_write_item(self, **kwargs) -> dict[str, Any]:
213219
214220
For put operations, encrypts items before writing.
215221
216-
The parameters and return value match the boto3 DynamoDB batch_write_item API:
222+
The input and output syntaxes match those for the boto3 DynamoDB ``batch_write_item`` API:
223+
217224
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/batch_write_item.html
218225
219226
Args:
220-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 batch_write_item API parameters.
221-
Any put operations in the "RequestItems" argument will be encrypted locally
222-
before being written to DynamoDB.
227+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``batch_write_item``
228+
request syntax. Items in ``"PutRequest"`` values in the ``"RequestItems"`` argument will be encrypted
229+
locally before being written to DynamoDB.
223230
224231
Returns:
225-
dict: The response from DynamoDB. This matches the boto3 batch_write_item API response.
232+
dict: The response from DynamoDB. This matches the boto3 ``batch_write_item`` response syntax.
226233
227234
"""
228235
return self._client_operation_logic(
@@ -242,15 +249,17 @@ def batch_get_item(self, **kwargs) -> dict[str, Any]:
242249
"""
243250
Get multiple items from one or more tables. Decrypts any returned items.
244251
245-
The parameters and return value match the boto3 DynamoDB batch_get_item API:
252+
The input and output syntaxes match those for the boto3 DynamoDB ``batch_get_item`` API:
253+
246254
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/batch_get_item.html
247255
248256
Args:
249-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 batch_get_item API parameters.
257+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``batch_get_item``
258+
request syntax.
250259
251260
Returns:
252-
dict: The response from DynamoDB. This matches the boto3 batch_get_item API response.
253-
The "Responses" field will be decrypted locally after being read from DynamoDB.
261+
dict: The response from DynamoDB. This matches the boto3 ``batch_get_item`` response syntax.
262+
The values in ``"Responses"`` will be decrypted locally after being read from DynamoDB.
254263
255264
"""
256265
return self._client_operation_logic(
@@ -270,15 +279,16 @@ def transact_get_items(self, **kwargs) -> dict[str, Any]:
270279
"""
271280
Get multiple items in a single transaction. Decrypts any returned items.
272281
273-
The parameters and return value match the boto3 DynamoDB transact_get_items API:
282+
The input and output syntaxes match those for the boto3 DynamoDB ``transact_get_items`` API:
283+
274284
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/transact_get_items.html
275285
276286
Args:
277-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 transact_get_items API
278-
parameters.
287+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``transact_get_items``
288+
request syntax.
279289
280290
Returns:
281-
dict: The response from DynamoDB. This matches the boto3 transact_get_items API response.
291+
dict: The response from DynamoDB. This matches the boto3 ``transact_get_items`` response syntax.
282292
283293
"""
284294
return self._client_operation_logic(
@@ -300,16 +310,17 @@ def transact_write_items(self, **kwargs) -> dict[str, Any]:
300310
301311
For put operations, encrypts items before writing.
302312
303-
The parameters and return value match the boto3 DynamoDB transact_write_items API:
313+
The input and output syntaxes match those for the boto3 DynamoDB ``transact_write_items`` API:
314+
304315
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/transact_write_items.html
305316
306317
Args:
307-
**kwargs: Keyword arguments to pass to the operation. These match the boto3 transact_write_items API
308-
parameters. Any put operations in the "TransactItems" argument will be encrypted locally
309-
before being written to DynamoDB.
318+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 ``transact_write_items``
319+
request syntax. Any ``"PutRequest"`` values in the ``"TransactItems"`` argument will be encrypted
320+
locally before being written to DynamoDB.
310321
311322
Returns:
312-
dict: The response from DynamoDB. This matches the boto3 transact_write_items API response.
323+
dict: The response from DynamoDB. This matches the boto3 ``transact_write_items`` response syntax.
313324
314325
"""
315326
return self._client_operation_logic(
@@ -351,8 +362,8 @@ def get_paginator(self, operation_name: str) -> EncryptedPaginator | botocore.cl
351362
operation_name (str): Name of operation for which to get paginator
352363
353364
Returns:
354-
EncryptedPaginator | botocore.client.Paginator: A paginator that will transparently decrypt items
355-
for scan/query operations, or the standard paginator for other operations.
365+
EncryptedPaginator | botocore.client.Paginator: An EncryptedPaginator that will transparently decrypt items
366+
for ``scan``/``query`` operations; for other operations, the standard paginator.
356367
357368
"""
358369
paginator = self._client.get_paginator(operation_name)

DynamoDbEncryption/runtimes/python/test/integ/encrypted/test_client.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
13
import boto3
24
import pytest
35
from boto3.dynamodb.types import TypeDeserializer, TypeSerializer
@@ -41,11 +43,16 @@
4143
basic_transact_write_item_put_request_ddb,
4244
basic_transact_write_item_put_request_dict,
4345
)
46+
from . import sort_dynamodb_json_lists
4447

4548
serializer = TypeSerializer()
4649
deserializer = TypeDeserializer()
4750

4851

52+
# Creates a matrix of tests for each value in param,
53+
# with a user-friendly string for test output:
54+
# expect_standard_dictionaries = True -> "standard_dicts"
55+
# expect_standard_dictionaries = False -> "ddb_json"
4956
@pytest.fixture(params=[True, False], ids=["standard_dicts", "ddb_json"])
5057
def expect_standard_dictionaries(request):
5158
return request.param
@@ -67,6 +74,10 @@ def plaintext_client(expect_standard_dictionaries):
6774
return client
6875

6976

77+
# Creates a matrix of tests for each value in param,
78+
# with a user-friendly string for test output:
79+
# encrypted = True -> "encrypted"
80+
# encrypted = False -> "plaintext"
7081
@pytest.fixture(params=[True, False], ids=["encrypted", "plaintext"])
7182
def encrypted(request):
7283
return request.param
@@ -80,6 +91,10 @@ def client(encrypted, expect_standard_dictionaries):
8091
return plaintext_client(expect_standard_dictionaries)
8192

8293

94+
# Creates a matrix of tests for each value in param,
95+
# with a user-friendly string for test output:
96+
# use_complex_item = True -> "complex_item"
97+
# use_complex_item = False -> "simple_item"
8398
@pytest.fixture(params=[True, False], ids=["complex_item", "simple_item"])
8499
def use_complex_item(request):
85100
return request.param
@@ -143,22 +158,6 @@ def get_item_request(expect_standard_dictionaries, test_item):
143158
return basic_get_item_request_ddb(test_item)
144159

145160

146-
def sort_dynamodb_json_lists(obj):
147-
"""
148-
Utility that recursively sorts all lists in a DynamoDB JSON-like structure.
149-
DynamoDB JSON uses lists to represent sets, so strict equality can fail.
150-
Sort lists to ensure consistent ordering when comparing expected and actual items.
151-
"""
152-
if isinstance(obj, dict):
153-
return {k: sort_dynamodb_json_lists(v) for k, v in obj.items()}
154-
elif isinstance(obj, list):
155-
try:
156-
return sorted(obj) # Sort lists for consistent comparison
157-
except TypeError:
158-
return obj # Not all lists are sortable; ex. complex_item_ddb's "list" attribute
159-
return obj
160-
161-
162161
def test_GIVEN_valid_put_and_get_requests_WHEN_put_and_get_THEN_round_trip_passes(
163162
client, put_item_request, get_item_request
164163
):

Examples/runtimes/python/DynamoDBEncryption/src/basic_put_get_example/with_encrypted_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
)
2121
from aws_cryptographic_material_providers.mpl.references import IKeyring
2222
from aws_dbesdk_dynamodb.encrypted.client import EncryptedClient
23-
from aws_dbesdk_dynamodb.models.dynamodb import (
23+
from aws_dbesdk_dynamodb.structures.dynamodb import (
2424
DynamoDbTableEncryptionConfig,
2525
DynamoDbTablesEncryptionConfig,
2626
)
27-
from aws_dbesdk_dynamodb.models.structured_encryption import (
27+
from aws_dbesdk_dynamodb.structures.structured_encryption import (
2828
CryptoAction,
2929
)
3030

0 commit comments

Comments
 (0)