aws / aws-dynamodb-encryption-python

Amazon DynamoDB Encryption Client for Python
Apache License 2.0
97 stars 56 forks source link

Support transactional methods in EncryptionClient #406

Open jplock opened 1 year ago

jplock commented 1 year ago

Problem:

Are not currently supported by the EncryptionClient and passed through to the underlying client.

Solution:

Fully implement transact_get_items() and transact_write_items() in the EncryptionClient

Out of scope:

Is there anything the solution will intentionally NOT address? No

Workaround

I was able to implement the following workaround to encrypt one of the Put requests within my transaction:

aws_kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=KEY_ARN)
actions = AttributeActions(
    default_action=CryptoAction.DO_NOTHING,
    attribute_actions={"access_token": CryptoAction.ENCRYPT_AND_SIGN},
)
encrypted_client = EncryptedClient(
    client=dynamodb.meta.client,
    materials_provider=aws_kms_cmp,
    attribute_actions=actions,
    expect_standard_dictionaries=True,
    auto_refresh_table_indexes=False
)

item = {
    "pk": f"USER#{user_id}#ITEM#{item_id}",
    "sk": "v0",
    "access_token": access_token,
    "institution_id": institution_id,
    "institution_name": institution.get("name"),
    "link_session_id": metadata.get("link_session_id"),
    "created_at": now,
}

def mock_write_method(**kwargs):
    return kwargs.get("Item")

encrypt_item = partial(
    encrypt_put_item,
    encrypted_client._encrypt_item,
    encrypted_client._item_crypto_config,
    mock_write_method,
)
encrypted_item = encrypt_item(TableName=TABLE_NAME, Item=item)

items = [
    {
        "Put": {
            "TableName": TABLE_NAME,
            "Item": encrypted_item
        }
    }
]
dynamodb_client.transact_write_items(TransactItems=items)
imabhichow commented 1 year ago

Hi @jplock

Thank you for your feature request, and for posting a workaround. You are correct that we currently do not support DDB Transactions in the DynamoDB Encryption Client for Python. I will keep this issue open for any future updates we may have.

In your workaround, one thing that you will need to be careful of is including any UPDATE in your Transact Write. DDB UPDATE can lead to signature verification failures on future reads if you do not include all signed fields in the update. See our documentation here: https://docs.aws.amazon.com/dynamodb-encryption-client/latest/devguide/troubleshooting.html#change-data-model

jplock commented 1 year ago

Thanks @imabhichow for the feedback. In my use-case I'm not updating records, always overwriting with a Put.