Skip to content

Commit 5df5f9c

Browse files
author
Lucas McDonald
committed
sync
1 parent e9f917b commit 5df5f9c

File tree

2 files changed

+157
-63
lines changed

2 files changed

+157
-63
lines changed

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

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -419,45 +419,25 @@ def update_item(self, **kwargs):
419419
output_item_to_ddb_transform_method=self._resource_to_client_shape_converter.update_item_response,
420420
)
421421

422-
def get_paginator(self, operation_name: str) -> EncryptedPaginator | botocore.client.Paginator:
422+
def execute_statement(self, **kwargs):
423423
"""
424-
Get a paginator from the underlying client.
424+
Calls ``execute_statement`` on the underlying client if the table is not configured for encryption.
425425
426-
If the paginator requested is for "scan" or "query", the paginator returned will
427-
transparently decrypt the returned items.
426+
If the table is configured for encryption, this operation will raise DynamoDbEncryptionTransformsException.
428427
429-
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#paginators
428+
The input and output syntaxes match those for the boto3 DynamoDB client ``execute_statement`` API:
429+
430+
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/execute_statement.html
430431
431432
Args:
432-
operation_name (str): Name of operation for which to get paginator
433+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 client ``execute_statement``
434+
request syntax.
433435
434436
Returns:
435-
EncryptedPaginator | botocore.client.Paginator: An EncryptedPaginator that will transparently decrypt items
436-
for ``scan``/``query`` operations; for other operations, the standard paginator.
437-
438-
"""
439-
paginator = self._client.get_paginator(operation_name)
440-
441-
if operation_name in ("scan", "query"):
442-
return EncryptedPaginator(
443-
paginator=paginator,
444-
encryption_config=self._encryption_config,
445-
expect_standard_dictionaries=self._expect_standard_dictionaries,
446-
)
447-
else:
448-
# The paginator can still be used for list_backups, list_tables, and list_tags_of_resource,
449-
# but there is nothing to encrypt/decrypt in these operations.
450-
return paginator
451-
452-
def execute_statement(self, **kwargs):
453-
"""
454-
Not implemented. Raises DynamoDbEncryptionTransformsException.
455-
456-
Args:
457-
**kwargs: Any arguments passed to this method
437+
dict: The response from DynamoDB. This matches the boto3 client ``execute_statement`` response syntax.
458438
459439
Raises:
460-
DynamoDbEncryptionTransformsException: This operation is not supported on encrypted tables.
440+
DynamoDbEncryptionTransformsException: If this operation is called for an encrypted table.
461441
462442
"""
463443
return self._client_operation_logic(
@@ -475,13 +455,23 @@ def execute_statement(self, **kwargs):
475455

476456
def execute_transaction(self, **kwargs):
477457
"""
478-
Not implemented. Raises DynamoDbEncryptionTransformsException.
458+
Calls ``execute_transaction`` on the underlying client if the table is not configured for encryption.
459+
460+
If the table is configured for encryption, this operation will raise DynamoDbEncryptionTransformsException.
461+
462+
The input and output syntaxes match those for the boto3 DynamoDB client ``execute_transaction`` API:
463+
464+
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/execute_transaction.html
479465
480466
Args:
481-
**kwargs: Any arguments passed to this method
467+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 client ``execute_transaction``
468+
request syntax.
469+
470+
Returns:
471+
dict: The response from DynamoDB. This matches the boto3 client ``execute_transaction`` response syntax.
482472
483473
Raises:
484-
DynamoDbEncryptionTransformsException: This operation is not supported on encrypted tables.
474+
DynamoDbEncryptionTransformsException: If this operation is called for an encrypted table.
485475
486476
"""
487477
return self._client_operation_logic(
@@ -499,13 +489,23 @@ def execute_transaction(self, **kwargs):
499489

500490
def batch_execute_statement(self, **kwargs):
501491
"""
502-
Not implemented. Raises DynamoDbEncryptionTransformsException.
492+
Calls ``batch_execute_statement`` on the underlying client if the table is not configured for encryption.
493+
494+
If the table is configured for encryption, this operation will raise DynamoDbEncryptionTransformsException.
495+
496+
The input and output syntaxes match those for the boto3 DynamoDB client ``batch_execute_statement`` API:
497+
498+
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/batch_execute_statement.html
503499
504500
Args:
505-
**kwargs: Any arguments passed to this method
501+
**kwargs: Keyword arguments to pass to the operation. This matches the boto3 client ``batch_execute_statement``
502+
request syntax.
503+
504+
Returns:
505+
dict: The response from DynamoDB. This matches the boto3 client ``batch_execute_statement`` response syntax.
506506
507507
Raises:
508-
DynamoDbEncryptionTransformsException: This operation is not supported on encrypted tables.
508+
DynamoDbEncryptionTransformsException: If this operation is called for an encrypted table.
509509
510510
"""
511511
return self._client_operation_logic(
@@ -521,6 +521,36 @@ def batch_execute_statement(self, **kwargs):
521521
output_item_to_ddb_transform_method=self._resource_to_client_shape_converter.batch_execute_statement_response,
522522
)
523523

524+
def get_paginator(self, operation_name: str) -> EncryptedPaginator | botocore.client.Paginator:
525+
"""
526+
Get a paginator from the underlying client.
527+
528+
If the paginator requested is for "scan" or "query", the paginator returned will
529+
transparently decrypt the returned items.
530+
531+
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#paginators
532+
533+
Args:
534+
operation_name (str): Name of operation for which to get paginator
535+
536+
Returns:
537+
EncryptedPaginator | botocore.client.Paginator: An EncryptedPaginator that will transparently decrypt items
538+
for ``scan``/``query`` operations; for other operations, the standard paginator.
539+
540+
"""
541+
paginator = self._client.get_paginator(operation_name)
542+
543+
if operation_name in ("scan", "query"):
544+
return EncryptedPaginator(
545+
paginator=paginator,
546+
encryption_config=self._encryption_config,
547+
expect_standard_dictionaries=self._expect_standard_dictionaries,
548+
)
549+
else:
550+
# The paginator can still be used for list_backups, list_tables, and list_tags_of_resource,
551+
# but there is nothing to encrypt/decrypt in these operations.
552+
return paginator
553+
524554
def _client_operation_logic(
525555
self,
526556
*,

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

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
simple_key_dict,
2525
)
2626
from ...requests import (
27-
basic_batch_execute_statement_request,
2827
basic_batch_get_item_request_ddb,
2928
basic_batch_get_item_request_dict,
3029
basic_batch_write_item_delete_request_ddb,
@@ -33,8 +32,12 @@
3332
basic_batch_write_item_put_request_dict,
3433
basic_delete_item_request_ddb,
3534
basic_delete_item_request_dict,
36-
basic_execute_statement_request,
37-
basic_execute_transaction_request,
35+
basic_execute_statement_request_encrypted_table,
36+
basic_execute_statement_request_plaintext_table,
37+
basic_execute_transaction_request_encrypted_table,
38+
basic_execute_transaction_request_plaintext_table,
39+
basic_batch_execute_statement_request_encrypted_table,
40+
basic_batch_execute_statement_request_plaintext_table,
3841
basic_get_item_request_ddb,
3942
basic_get_item_request_dict,
4043
basic_put_item_request_ddb,
@@ -428,68 +431,129 @@ def test_WHEN_update_item_with_signed_attribute_THEN_raises_DynamoDbEncryptionTr
428431
client.update_item(**update_item_request_signed_attribute)
429432

430433

434+
@pytest.fixture(params=[True, False], ids=["encrypted_table", "plaintext_table"])
435+
def execute_uses_encrypted_table(request):
436+
return request.param
437+
431438
@pytest.fixture
432-
def execute_statement_request():
433-
return basic_execute_statement_request()
439+
def execute_statement_request(execute_uses_encrypted_table):
440+
if execute_uses_encrypted_table:
441+
return basic_execute_statement_request_encrypted_table()
442+
return basic_execute_statement_request_plaintext_table()
434443

435444

436-
def test_WHEN_execute_statement_THEN_raises_DynamoDbEncryptionTransformsException(
445+
def test_WHEN_execute_statement_for_encrypted_table_THEN_raises_DynamoDbEncryptionTransformsException(
437446
client,
438447
execute_statement_request,
439448
encrypted,
449+
execute_uses_encrypted_table,
440450
):
441451
"""Test that execute_statement raises DynamoDbEncryptionTransformsException."""
442452
if not encrypted:
443453
pytest.skip("Skipping negative test for plaintext client")
444454

445-
# Given: Encrypted client and update item parameters
446-
# Then: DynamoDbEncryptionTransformsException is raised
447-
with pytest.raises(DynamoDbEncryptionTransformsException):
448-
# When: Calling update_item
449-
client.execute_statement(**execute_statement_request)
455+
if execute_uses_encrypted_table:
456+
# Given: Encrypted client and execute_statement request on encrypted table
457+
# Then: DynamoDbEncryptionTransformsException is raised
458+
with pytest.raises(DynamoDbEncryptionTransformsException):
459+
# When: Calling execute_statement
460+
client.execute_statement(**execute_statement_request)
461+
else:
462+
pytest.skip("Skipping test for plaintext table; this test is only for encrypted tables")
463+
464+
def test_WHEN_execute_statement_for_plaintext_table_THEN_passes(
465+
client,
466+
execute_statement_request,
467+
execute_uses_encrypted_table,
468+
):
469+
if execute_uses_encrypted_table:
470+
pytest.skip("Skipping test for encrypted table; this test is only for plaintext tables")
450471

472+
# Given: Client calls execute_statement on plaintext table
473+
# When: Calling execute_statement
474+
response = client.execute_statement(**execute_statement_request)
475+
# Then: Success
476+
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
451477

452478
@pytest.fixture
453-
def execute_transaction_request():
454-
return basic_execute_transaction_request()
479+
def execute_transaction_request(execute_uses_encrypted_table):
480+
if execute_uses_encrypted_table:
481+
return basic_execute_transaction_request_encrypted_table()
482+
return basic_execute_transaction_request_plaintext_table()
455483

456484

457-
def test_WHEN_execute_transaction_THEN_raises_DynamoDbEncryptionTransformsException(
485+
def test_WHEN_execute_transaction_for_encrypted_table_THEN_raises_DynamoDbEncryptionTransformsException(
458486
client,
459487
execute_transaction_request,
460488
encrypted,
489+
execute_uses_encrypted_table,
461490
):
462491
"""Test that execute_transaction raises DynamoDbEncryptionTransformsException."""
463492
if not encrypted:
464493
pytest.skip("Skipping negative test for plaintext client")
494+
495+
if execute_uses_encrypted_table:
496+
# Given: Encrypted client and execute_transaction request on encrypted table
497+
# Then: DynamoDbEncryptionTransformsException is raised
498+
with pytest.raises(DynamoDbEncryptionTransformsException):
499+
# When: Calling execute_transaction
500+
client.execute_transaction(**execute_transaction_request)
501+
else:
502+
pytest.skip("Skipping test for plaintext table; this test is only for encrypted tables")
465503

466-
# Given: Encrypted client and update item parameters
467-
# Then: DynamoDbEncryptionTransformsException is raised
468-
with pytest.raises(DynamoDbEncryptionTransformsException):
469-
# When: Calling update_item
470-
client.execute_transaction(**execute_transaction_request)
504+
def test_WHEN_execute_transaction_for_plaintext_table_THEN_passes(
505+
client,
506+
execute_transaction_request,
507+
execute_uses_encrypted_table,
508+
):
509+
if execute_uses_encrypted_table:
510+
pytest.skip("Skipping test for encrypted table; this test is only for plaintext tables")
471511

512+
# Given: Client calls execute_transaction on plaintext table
513+
# When: Calling execute_transaction
514+
response = client.execute_transaction(**execute_transaction_request)
515+
# Then: Success
516+
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
472517

473518
@pytest.fixture
474-
def batch_execute_statement_request():
475-
return basic_batch_execute_statement_request()
519+
def batch_execute_statement_request(execute_uses_encrypted_table):
520+
if execute_uses_encrypted_table:
521+
return basic_batch_execute_statement_request_encrypted_table()
522+
return basic_batch_execute_statement_request_plaintext_table()
476523

477524

478-
def test_WHEN_batch_execute_statement_THEN_raises_DynamoDbEncryptionTransformsException(
525+
def test_WHEN_batch_execute_statement_for_encrypted_table_THEN_raises_DynamoDbEncryptionTransformsException(
479526
client,
480527
batch_execute_statement_request,
481528
encrypted,
529+
execute_uses_encrypted_table,
482530
):
483531
"""Test that batch_execute_statement raises DynamoDbEncryptionTransformsException."""
484532
if not encrypted:
485533
pytest.skip("Skipping negative test for plaintext client")
486534

487-
# Given: Encrypted client and update item parameters
488-
# Then: DynamoDbEncryptionTransformsException is raised
489-
with pytest.raises(DynamoDbEncryptionTransformsException):
490-
# When: Calling update_item
491-
client.batch_execute_statement(**batch_execute_statement_request)
535+
if execute_uses_encrypted_table:
536+
# Given: Encrypted client and batch_execute_statement request on encrypted table
537+
# Then: DynamoDbEncryptionTransformsException is raised
538+
with pytest.raises(DynamoDbEncryptionTransformsException):
539+
# When: Calling batch_execute_statement
540+
client.batch_execute_statement(**batch_execute_statement_request)
541+
else:
542+
pytest.skip("Skipping test for plaintext table; this test is only for encrypted tables")
492543

544+
def test_WHEN_batch_execute_statement_for_plaintext_table_THEN_passes(
545+
client,
546+
batch_execute_statement_request,
547+
execute_uses_encrypted_table,
548+
):
549+
if execute_uses_encrypted_table:
550+
pytest.skip("Skipping test for encrypted table; this test is only for plaintext tables")
551+
552+
# Given: Client calls batch_execute_statement on plaintext table
553+
# When: Calling batch_execute_statement
554+
response = client.batch_execute_statement(**batch_execute_statement_request)
555+
# Then: Success
556+
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
493557

494558
def test_WHEN_get_paginator_THEN_correct_paginator_is_returned():
495559
"""Test get_paginator for scan and query operations."""

0 commit comments

Comments
 (0)