Skip to content

WIP feat(python): Legacy Extern #1938

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: python-poc
Choose a base branch
from

Conversation

imabhichow
Copy link

Issue #, if available:

Description of changes:

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@imabhichow imabhichow force-pushed the imabhichow/legacy-extern branch 3 times, most recently from 1b314f4 to 21d22dd Compare June 12, 2025 23:26
# TODO: Implement this
# Create and return the legacy override instance
legacy_instance = InternalLegacyOverride()
legacy_instance.encryptor = legacy_override.encryptor
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at this, we could actually ignore the encryptor and just call Legacy DDBEC's ItemEncryptor methods encrypt_dynamo_item or encrypt_python_item based on Legacy encryptor(EncryptedClient/EncryptedTable) instance

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure what you mean, but this sounds interesting. If you think it's better, try writing it and I'll take a look

@imabhichow imabhichow force-pushed the imabhichow/legacy-extern branch from 21d22dd to 522b0f9 Compare June 13, 2025 09:27
Copy link
Contributor

@lucasmcdonald3 lucasmcdonald3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most comments are nits/cleanups.

I'm most interested in the other interfaces, so let's get started on that. There may be some fun stuff with how all DBESDK interfaces interact with the EncryptedClient that we should take a look at

@@ -13,6 +13,7 @@ include = ["**/internaldafny/generated/*.py"]
[tool.poetry.dependencies]
python = "^3.11.0"
aws-cryptographic-material-providers = { path = "../../../submodules/MaterialProviders/AwsCryptographicMaterialProviders/runtimes/python", develop = false}
dynamodb_encryption_sdk = "^3.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DDBEC should be an optional dependency.
Take a look at this page: https://python-poetry.org/docs/pyproject/#extras
You should set it up so that one could install it with a pip command like pip install aws-dbesdk-dynamodb[legacy-ddbec]

Comment on lines +99 to +101
table_name = _dafny.string_of(config.logicalTableName)
partition_key_name = _dafny.string_of(config.partitionKeyName)
sort_key_name = _dafny.string_of(config.sortKeyName.value) if config.sortKeyName.is_Some else None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for steering you down the wrong track here, but we shouldn't use _dafny.string_of for anything that handles data.
Its implementation uses a different byte order than the rest of our code.
Check out this dafny-to-native string expression and make a method for it in this file: https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/python-poc/DynamoDbEncryption/runtimes/python/src/aws_dbesdk_dynamodb/smithygenerated/aws_cryptography_dbencryptionsdk_dynamodb_itemencryptor/dafny_to_smithy.py#L146-L148
I'd replace all instances of _dafny.string_of unless you know it will never handle "special" (non-BMP) characters

def EncryptItem(input):
# TODO: Implement this
return Wrappers.Result_Failure("TODO-legacy-Encryptitem")
# Map the action from the config to legacy actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation in this file from here down is odd compared to above

from dynamodb_encryption_sdk.material_providers.aws_kms import AwsKmsCryptographicMaterialsProvider


def setup_pure_awsdbe_client(kms_key_id: str, ddb_table_name: str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should test this with all the boto3 interfaces: EncryptedTables, EncryptedResources, and EncryptedPaginators, since all of these interfaces accept DynamoDbTableEncryptionConfig.

For EncryptedTables and EncryptedResources in particular, we need to make sure that if someone provides a legacy config with a legacy DDBEC encrypted client, then the items are still transformed correctly.
(I think there could be some hiccups with the PR as-is, depending on how our Dafny code works.)

Do some testing and let me know what you find, we can chat about next steps depending on what happens
(We might also need the InternalLegacyOverride to support the legacy interfaces if the items aren't transformed correctly, but we'll see what happens)

I think EncryptedPaginator should just work though.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is valuable feedback; I plan on doing some experiments testing all potential combinations (matrix), such as each DB-ESDK Interface with each Legacy DDBEC Interface.

Legacy DDBEC also provides a helpful util that transforms python_dict to ddb_item. If we can utilize that util, we could support all interfaces without relying on the encryptors by just calling the legacy item encryptor methods with all matrix combinations like (DB ESDK EncryptedTable with Legacy DDBEC EncryptedPaginator).

# Precondition: The encryptor MUST be a DynamoDBEncryptor
if not _HAS_LEGACY_DDBEC:
return InternalLegacyOverride.CreateBuildFailure(
InternalLegacyOverride.CreateError("Could not find aws-dynamodb-encryption-python installation")
)
if not isinstance(maybe_encryptor, EncryptedClient):
if not isinstance(legacy_override.encryptor, EncryptedClient):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we may need to extend this to support legacy EncryptedTable, EncryptedResource, and EncryptedPaginator, depending on what happens when you test the new interfaces for those.

policy=policy,
)

# 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that protect your data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numbering is off

Comment on lines +13 to +17
- Create a pure AWS DBESDK client that can only read items encrypted with AWS DBESDK
- Create an AWS DBESDK client with legacy override that can read legacy items
- Use the pure client to encrypt new items
- Use the client with legacy override to read both legacy and new items
- Re-encrypt legacy items with the pure AWS DBESDK client
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's some redundancies here -- could you tighten this up?

@@ -0,0 +1,9 @@
"""Test constants."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the copyright header

Co-authored-by: Lucas McDonald <lucasmcdonald3@gmail.com>
@imabhichow imabhichow force-pushed the imabhichow/legacy-extern branch from e75c12e to 0142f15 Compare June 16, 2025 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants