From 51a397569c7fe68f1d7b3b80839c7fec97fd9c4c Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 29 May 2025 15:13:54 -0700 Subject: [PATCH] sync --- .gitignore | 7 +- DynamoDbEncryption/Makefile | 92 +++++++++++++++ DynamoDbEncryption/runtimes/python/.gitignore | 17 +++ DynamoDbEncryption/runtimes/python/README.md | 44 ++++++++ .../runtimes/python/pyproject.toml | 106 ++++++++++++++++++ .../python/DynamoDBEncryption/.gitignore | 17 +++ Examples/runtimes/python/pyproject.toml | 49 ++++++++ README.md | 1 + TestVectors/Makefile | 64 ++++++++++- TestVectors/runtimes/python/.gitignore | 17 +++ TestVectors/runtimes/python/README.md | 24 ++++ TestVectors/runtimes/python/pyproject.toml | 24 ++++ 12 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 DynamoDbEncryption/runtimes/python/.gitignore create mode 100644 DynamoDbEncryption/runtimes/python/README.md create mode 100644 DynamoDbEncryption/runtimes/python/pyproject.toml create mode 100644 Examples/runtimes/python/DynamoDBEncryption/.gitignore create mode 100644 Examples/runtimes/python/pyproject.toml create mode 100644 TestVectors/runtimes/python/.gitignore create mode 100644 TestVectors/runtimes/python/README.md create mode 100644 TestVectors/runtimes/python/pyproject.toml diff --git a/.gitignore b/.gitignore index 4c01b8aed..7a03a225a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,9 @@ specification_compliance_report.html /.smithy.lsp.log # logs -*.log \ No newline at end of file +*.log + +# Performance testing artifacts +*.png +*.dot +*.prof \ No newline at end of file diff --git a/DynamoDbEncryption/Makefile b/DynamoDbEncryption/Makefile index ec52ca43d..65cc8292d 100644 --- a/DynamoDbEncryption/Makefile +++ b/DynamoDbEncryption/Makefile @@ -3,6 +3,7 @@ CORES=2 +ENABLE_EXTERN_PROCESSING=1 TRANSPILE_TESTS_IN_RUST=1 include ../SharedMakefile.mk @@ -99,3 +100,94 @@ SERVICE_DEPS_DynamoDbEncryptionTransforms := \ DynamoDbEncryption/dafny/DynamoDbEncryption \ DynamoDbEncryption/dafny/StructuredEncryption \ DynamoDbEncryption/dafny/DynamoDbItemEncryptor + +# Python + +PYTHON_MODULE_NAME=aws_dbesdk_dynamodb + +TRANSLATION_RECORD_PYTHON := \ + --translation-record ../submodules/MaterialProviders/StandardLibrary/runtimes/python/src/smithy_dafny_standard_library/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/ComAmazonawsKms/runtimes/python/src/aws_cryptography_internal_kms/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/ComAmazonawsDynamodb/runtimes/python/src/aws_cryptography_internal_dynamodb/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/AwsCryptographyPrimitives/runtimes/python/src/aws_cryptography_primitives/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/AwsCryptographicMaterialProviders/runtimes/python/src/aws_cryptographic_material_providers/internaldafny/generated/dafny_src-py.dtr + +PYTHON_DEPENDENCY_MODULE_NAMES := \ + --dependency-library-name=aws.cryptography.primitives=aws_cryptography_primitives \ + --dependency-library-name=com.amazonaws.kms=aws_cryptography_internal_kms \ + --dependency-library-name=com.amazonaws.dynamodb=aws_cryptography_internal_dynamodb \ + --dependency-library-name=aws.cryptography.materialProviders=aws_cryptographic_material_providers \ + --dependency-library-name=aws.cryptography.keyStore=aws_cryptographic_material_providers \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.structuredEncryption=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb.itemEncryptor=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb.transforms=aws_dbesdk_dynamodb \ + +# Override default test_python to run tox environment for Dafny tests +test_python: + rm -rf runtimes/python/.tox + python3 -m tox -c runtimes/python -e dafnytests --verbose + +# Constants for languages that drop extern names (Python, Go) + +DYNAMODB_TYPES_FILE_PATH=dafny/DynamoDbEncryption/Model/AwsCryptographyDbEncryptionSdkDynamoDbTypes.dfy +DYNAMODB_TYPES_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.internaldafny.types\" } AwsCryptographyDbEncryptionSdkDynamoDbTypes" +DYNAMODB_TYPES_FILE_WITHOUT_EXTERN_STRING="module AwsCryptographyDbEncryptionSdkDynamoDbTypes" + +DYNAMODB_INDEX_FILE_PATH=dafny/DynamoDbEncryption/src/Index.dfy +DYNAMODB_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.internaldafny\" } DynamoDbEncryption" +DYNAMODB_INDEX_FILE_WITHOUT_EXTERN_STRING="module DynamoDbEncryption" + +ITEMENCRYPTOR_TYPES_FILE_PATH=dafny/DynamoDbItemEncryptor/Model/AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorTypes.dfy +ITEMENCRYPTOR_TYPES_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.internaldafny.types\" } AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorTypes" +ITEMENCRYPTOR_TYPES_FILE_WITHOUT_EXTERN_STRING="module AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorTypes" + +ITEMENCRYPTOR_INDEX_FILE_PATH=dafny/DynamoDbItemEncryptor/src/Index.dfy +ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.internaldafny\" } DynamoDbItemEncryptor" +ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING="module DynamoDbItemEncryptor" + +ITEMENCRYPTOR_LEGACY_FILE_PATH=dafny/DynamoDbItemEncryptor/src/InternalLegacyOverride.dfy +ITEMENCRYPTOR_LEGACY_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.internaldafny.legacy\"} InternalLegacyOverride {" +ITEMENCRYPTOR_LEGACY_FILE_WITHOUT_EXTERN_STRING="module InternalLegacyOverride {" + +TRANSFORMS_TYPES_FILE_PATH=dafny/DynamoDbEncryptionTransforms/Model/AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.dfy +TRANSFORMS_TYPES_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.transforms.internaldafny.types\" } AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes" +TRANSFORMS_TYPES_FILE_WITHOUT_EXTERN_STRING="module AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes" + +TRANSFORMS_INDEX_FILE_PATH=dafny/DynamoDbEncryptionTransforms/src/Index.dfy +TRANSFORMS_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.transforms.internaldafny\" } DynamoDbEncryptionTransforms" +TRANSFORMS_INDEX_FILE_WITHOUT_EXTERN_STRING="module DynamoDbEncryptionTransforms" + +STRUCTUREDENCRYPTION_TYPES_FILE_PATH=dafny/StructuredEncryption/Model/AwsCryptographyDbEncryptionSdkStructuredEncryptionTypes.dfy +STRUCTUREDENCRYPTION_TYPES_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.structuredencryption.internaldafny.types\" } AwsCryptographyDbEncryptionSdkStructuredEncryptionTypes" +STRUCTUREDENCRYPTION_TYPES_FILE_WITHOUT_EXTERN_STRING="module AwsCryptographyDbEncryptionSdkStructuredEncryptionTypes" + +STRUCTUREDENCRYPTION_INDEX_FILE_PATH=dafny/StructuredEncryption/src/Index.dfy +STRUCTUREDENCRYPTION_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.structuredencryption.internaldafny\" } StructuredEncryption" +STRUCTUREDENCRYPTION_INDEX_FILE_WITHOUT_EXTERN_STRING="module StructuredEncryption" + +_sed_types_file_remove_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(DYNAMODB_TYPES_FILE_PATH) SED_BEFORE_STRING=$(DYNAMODB_TYPES_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(DYNAMODB_TYPES_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_TYPES_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_TYPES_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_TYPES_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(TRANSFORMS_TYPES_FILE_PATH) SED_BEFORE_STRING=$(TRANSFORMS_TYPES_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(TRANSFORMS_TYPES_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(STRUCTUREDENCRYPTION_TYPES_FILE_PATH) SED_BEFORE_STRING=$(STRUCTUREDENCRYPTION_TYPES_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(STRUCTUREDENCRYPTION_TYPES_FILE_WITHOUT_EXTERN_STRING) + +_sed_index_file_remove_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(DYNAMODB_INDEX_FILE_PATH) SED_BEFORE_STRING=$(DYNAMODB_INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(DYNAMODB_INDEX_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_INDEX_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_LEGACY_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_LEGACY_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_LEGACY_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(TRANSFORMS_INDEX_FILE_PATH) SED_BEFORE_STRING=$(TRANSFORMS_INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(TRANSFORMS_INDEX_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(STRUCTUREDENCRYPTION_INDEX_FILE_PATH) SED_BEFORE_STRING=$(STRUCTUREDENCRYPTION_INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(STRUCTUREDENCRYPTION_INDEX_FILE_WITHOUT_EXTERN_STRING) + +_sed_types_file_add_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(DYNAMODB_TYPES_FILE_PATH) SED_BEFORE_STRING=$(DYNAMODB_TYPES_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(DYNAMODB_TYPES_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_TYPES_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_TYPES_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_TYPES_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(TRANSFORMS_TYPES_FILE_PATH) SED_BEFORE_STRING=$(TRANSFORMS_TYPES_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(TRANSFORMS_TYPES_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(STRUCTUREDENCRYPTION_TYPES_FILE_PATH) SED_BEFORE_STRING=$(STRUCTUREDENCRYPTION_TYPES_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(STRUCTUREDENCRYPTION_TYPES_FILE_WITH_EXTERN_STRING) + +_sed_index_file_add_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(DYNAMODB_INDEX_FILE_PATH) SED_BEFORE_STRING=$(DYNAMODB_INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(DYNAMODB_INDEX_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_INDEX_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_LEGACY_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_LEGACY_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_LEGACY_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(TRANSFORMS_INDEX_FILE_PATH) SED_BEFORE_STRING=$(TRANSFORMS_INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(TRANSFORMS_INDEX_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(STRUCTUREDENCRYPTION_INDEX_FILE_PATH) SED_BEFORE_STRING=$(STRUCTUREDENCRYPTION_INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(STRUCTUREDENCRYPTION_INDEX_FILE_WITH_EXTERN_STRING) diff --git a/DynamoDbEncryption/runtimes/python/.gitignore b/DynamoDbEncryption/runtimes/python/.gitignore new file mode 100644 index 000000000..aaf44d4cd --- /dev/null +++ b/DynamoDbEncryption/runtimes/python/.gitignore @@ -0,0 +1,17 @@ +# Python build artifacts +__pycache__ +**/__pycache__ +*.pyc +src/**.egg-info/ +build +poetry.lock +**/poetry.lock +dist + +# Dafny-generated Python +**/internaldafny/generated + +# Python test artifacts +.tox +.pytest_cache + diff --git a/DynamoDbEncryption/runtimes/python/README.md b/DynamoDbEncryption/runtimes/python/README.md new file mode 100644 index 000000000..6f6980e01 --- /dev/null +++ b/DynamoDbEncryption/runtimes/python/README.md @@ -0,0 +1,44 @@ +# Python AWS Database Encryption SDK for DynamoDB + +[![MPL-python-tests](https://github.com/aws/aws-database-encryption-sdk-dynamodb/actions/workflows/push.yml/badge.svg)](https://github.com/aws/aws-database-encryption-sdk-dynamodb/actions/workflows/push.yml) +[![Code style: black](https://img.shields.io/badge/code_style-black-000000.svg)](https://github.com/ambv/black) +[![Documentation Status](https://readthedocs.org/projects/aws-dbesdk-dynamodb-python/badge/)](https://aws-dbesdk-dynamodb-python.readthedocs.io/en/latest/) + +This is the official implementation of the AWS Database Encryption SDK for DynamoDB in Python. + +The latest documentation can be found at [Read the Docs](https://aws-dbesdk-dynamodb-python.readthedocs.io/en/latest/). + +Find the source code on [GitHub](https://github.com/aws/aws-database-encryption-sdk-dynamodb). + +## Security + +If you discover a potential security issue in this project +we ask that you notify AWS/Amazon Security via our +[vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). +Please **do not** create a public GitHub issue. + +## Getting Started + +### Required Prerequisites + +- Python 3.11+ +- aws-cryptographic-material-providers 1.10.0+ + +### Installation + +> **Note:** +> If you have not already installed [cryptography](https://cryptography.io/en/latest/), you might need to install additional prerequisites as +> detailed in the [cryptography installation guide](https://cryptography.io/en/latest/installation/) for your operating system. + +```bash +$ pip install aws-dbesdk-dynamodb +``` + +### Concepts + +The AWS Database Encryption SDK for DynamoDB (DBESDK-DynamoDB) is available in multiple languages. +The concepts in the Python implementation of the DBESDK-DynamoDB are the same as in other languages. +For more information on concepts in the DBESDK-DynamoDB, see the [README](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/README.md) for all languages. + +DBESDK-DynamoDB uses cryptographic material providers from the AWS Cryptographic Material Providers Library (MPL). +For more information on the MPL, see its [README](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/README.md) or [readthedocs](https://aws-cryptographic-material-providers-library.readthedocs.io/en/latest/) page. diff --git a/DynamoDbEncryption/runtimes/python/pyproject.toml b/DynamoDbEncryption/runtimes/python/pyproject.toml new file mode 100644 index 000000000..8456520b3 --- /dev/null +++ b/DynamoDbEncryption/runtimes/python/pyproject.toml @@ -0,0 +1,106 @@ +[tool.poetry] +name = "aws-dbesdk-dynamodb" +version = "0.1.0" +description = "" +authors = ["AWS Crypto Tools "] +packages = [ + { include = "aws_dbesdk_dynamodb", from = "src" }, +] +# Include all of the following .gitignored files in package distributions, +# even though it is not included in version control +include = ["**/internaldafny/generated/*.py"] + +[tool.poetry.dependencies] +python = "^3.11.0" +aws-cryptographic-material-providers = { path = "../../../submodules/MaterialProviders/AwsCryptographicMaterialProviders/runtimes/python", develop = false} + +# Package testing + +[tool.poetry.group.test] +optional = true + +[tool.poetry.group.test.dependencies] +pytest = "^7.4.0" +pytest-cov = "^6" +mock = "^4.0.3" + +# Package release + +[tool.poetry.group.release] +optional = true + +[tool.poetry.group.release.dependencies] +poetry = "1.8.3" +twine = "5.1.1" +wheel = "0.38.4" + +# Package documentation + +[tool.poetry.group.docs] +optional = true + +[tool.poetry.group.docs.dependencies] +toml = "^0.10.2" +myst-parser = "^4" +sphinx = "^7" +sphinx_rtd_theme = "^2" + +# Package linting + +[tool.poetry.group.linting] +optional = true + +[tool.poetry.group.linting.dependencies] +ruff = "^0.11.5" +black = "^25.1.0" + +[tool.ruff] +exclude = [ + # Don't bother linting Dafny-generated code + "internaldafny", + # Don't re-lint Smithy-generated code + "smithygenerated", +] +line-length=120 +indent-width=4 +target-version = "py311" + +[tool.ruff.lint] +# Choose linting tools +select = [ + # pycodestyle: spacing, line length + "E", + # pyflakes: unused imports/variables + "F", + # isort: import sorting + "I", + # pydocstyle: docstring style + "D", +] +# Ignore incompatible linting options +ignore=[ + "D203", # `incorrect-blank-line-before-class`; incompatible with `no-blank-line-before-class` (D211) + "D212", # `multi-line-summary-first-line`; incompatible with `multi-line-summary-second-line` (D213) +] + +[tool.ruff.lint.per-file-ignores] +"src/aws_dbesdk_dynamodb/internal/*" = [ + # Ignore all "public"-related linting errors for internal modules + "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", + # Ignore opinionated docstring linting errors for internal modules + "D205", "D400", "D401", "D403", "D404", "D415", +] +"test/*" = [ + # Ignore all "public"- and docstring-related linting errors for test modules + "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", + # Ignore opinionated docstring linting errors for test modules + "D205", "D400", "D401", "D403", "D404", "D415", +] + +[tool.black] +# Don't bother linting Dafny-generated code; don't re-lint Smithy-generated code +exclude = "/(internaldafny|smithygenerated)(/|$)" + +[build-system] +requires = ["poetry-core<2.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/Examples/runtimes/python/DynamoDBEncryption/.gitignore b/Examples/runtimes/python/DynamoDBEncryption/.gitignore new file mode 100644 index 000000000..61d5202d8 --- /dev/null +++ b/Examples/runtimes/python/DynamoDBEncryption/.gitignore @@ -0,0 +1,17 @@ +# Python build artifacts +__pycache__ +**/__pycache__ +*.pyc +src/**.egg-info/ +build +poetry.lock +**/poetry.lock +dist + +# Dafny-generated Python +**/internaldafny/generated/*.py + +# Python test artifacts +.tox +.pytest_cache + diff --git a/Examples/runtimes/python/pyproject.toml b/Examples/runtimes/python/pyproject.toml new file mode 100644 index 000000000..7ba0c8341 --- /dev/null +++ b/Examples/runtimes/python/pyproject.toml @@ -0,0 +1,49 @@ +[tool.poetry] +name = "aws-dbesdk-dynamodb-examples" +version = "0.1.0" +description = "" +authors = ["AWS Crypto Tools "] + +[tool.poetry.dependencies] +python = "^3.11.0" +aws-dbesdk-dynamodb = { path = "../../../DynamoDbEncryption/runtimes/python", develop = false} + +[tool.poetry.group.test.dependencies] +pytest = "^7.4.0" +tox = "^3" + +[build-system] +requires = ["poetry-core<2.0.0"] +build-backend = "poetry.core.masonry.api" + +# Package linting + +[tool.poetry.group.linting] +optional = true + +[tool.poetry.group.linting.dependencies] +ruff = "^0.11.5" +black = "^25.1.0" + +[tool.ruff] +line-length=120 +indent-width=4 +target-version = "py311" + +[tool.ruff.lint] +# Choose linting tools +select = [ + # pycodestyle: spacing, line length + "E", + # pyflakes: unused imports/variables + "F", + # isort: import sorting + "I", + # pydocstyle: docstring style + "D", +] +# Ignore incompatible linting options +ignore=[ + "D203", # `incorrect-blank-line-before-class`; incompatible with `no-blank-line-before-class` (D211) + "D212", # `multi-line-summary-first-line`; incompatible with `multi-line-summary-second-line` (D213) +] diff --git a/README.md b/README.md index 73375e7e6..13faf30d9 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ You need an Amazon Web Services (AWS) account to use the DB-ESDK for DynamoDB as - .NET - Dafny - Rust +- Python # Contributing diff --git a/TestVectors/Makefile b/TestVectors/Makefile index f918bfb7d..08a7f4097 100644 --- a/TestVectors/Makefile +++ b/TestVectors/Makefile @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 CORES=2 +ENABLE_EXTERN_PROCESSING=1 TRANSPILE_TESTS_IN_RUST=1 include ../SharedMakefile.mk @@ -128,4 +129,65 @@ _remove_wrapped_client_rust: $(MAKE) _sed_file SED_FILE_PATH=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_DYNAMODB) SED_BEFORE_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_FROM_1) SED_AFTER_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_TO_1) $(MAKE) _sed_file SED_FILE_PATH=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_DYNAMODB) SED_BEFORE_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_FROM_2) SED_AFTER_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_TO_2) $(MAKE) _sed_file SED_FILE_PATH=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_DYNAMODB_STRUCTURED_ENCRYPTION) SED_BEFORE_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_FROM_1) SED_AFTER_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_TO_1) - $(MAKE) _sed_file SED_FILE_PATH=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_DYNAMODB_STRUCTURED_ENCRYPTION) SED_BEFORE_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_FROM_2) SED_AFTER_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_TO_2) \ No newline at end of file + $(MAKE) _sed_file SED_FILE_PATH=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_DYNAMODB_STRUCTURED_ENCRYPTION) SED_BEFORE_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_FROM_2) SED_AFTER_STRING=$(REMOVE_WRAPPED_CLIENT_AFTER_POLYMORPH_RUST_TO_2) + +# Python + +PYTHON_MODULE_NAME=aws_dbesdk_dynamodb_test_vectors + +TRANSLATION_RECORD_PYTHON := \ + --translation-record ../submodules/MaterialProviders/StandardLibrary/runtimes/python/src/smithy_dafny_standard_library/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/ComAmazonawsKms/runtimes/python/src/aws_cryptography_internal_kms/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/ComAmazonawsDynamodb/runtimes/python/src/aws_cryptography_internal_dynamodb/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/AwsCryptographyPrimitives/runtimes/python/src/aws_cryptography_primitives/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/AwsCryptographicMaterialProviders/runtimes/python/src/aws_cryptographic_material_providers/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../submodules/MaterialProviders/TestVectorsAwsCryptographicMaterialProviders/runtimes/python/src/aws_cryptography_materialproviders_test_vectors/internaldafny/generated/dafny_src-py.dtr \ + --translation-record ../DynamoDbEncryption/runtimes/python/src/aws_dbesdk_dynamodb/internaldafny/generated/dafny_src-py.dtr + +PYTHON_DEPENDENCY_MODULE_NAMES := \ + --dependency-library-name=aws.cryptography.primitives=aws_cryptography_primitives \ + --dependency-library-name=com.amazonaws.kms=aws_cryptography_internal_kms \ + --dependency-library-name=com.amazonaws.dynamodb=aws_cryptography_internal_dynamodb \ + --dependency-library-name=aws.cryptography.materialProviders=aws_cryptographic_material_providers \ + --dependency-library-name=aws.cryptography.keyStore=aws_cryptographic_material_providers \ + --dependency-library-name=aws.cryptography.materialProvidersTestVectorKeys=aws_cryptography_materialproviders_test_vectors \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.structuredEncryption=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb.itemEncryptor=aws_dbesdk_dynamodb \ + --dependency-library-name=aws.cryptography.dbEncryptionSdk.dynamoDb.transforms=aws_dbesdk_dynamodb \ + +# Constants for languages that drop extern names (Python, Go) + +INDEX_FILE_PATH=dafny/DDBEncryption/src/LibraryIndex.dfy +INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.internaldafny.wrapped\"} WrappedDynamoDbEncryption refines WrappedAbstractAwsCryptographyDynamoDbEncryptionService" +INDEX_FILE_WITHOUT_EXTERN_STRING="module WrappedDynamoDbEncryption refines WrappedAbstractAwsCryptographyDynamoDbEncryptionService" + +ITEMENCRYPTOR_INDEX_FILE_PATH=dafny/WrappedDynamoDbItemEncryptor/src/Index.dfy +ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.internaldafny.wrapped\" } WrappedItemEncryptor refines WrappedAbstractAwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorService {" +ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING="module WrappedItemEncryptor refines WrappedAbstractAwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorService {" + +_sed_index_file_add_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(INDEX_FILE_PATH) SED_BEFORE_STRING=$(INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(INDEX_FILE_WITH_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_INDEX_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING) + +_sed_index_file_remove_extern: + $(MAKE) _sed_file SED_FILE_PATH=$(INDEX_FILE_PATH) SED_BEFORE_STRING=$(INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(INDEX_FILE_WITHOUT_EXTERN_STRING) + $(MAKE) _sed_file SED_FILE_PATH=$(ITEMENCRYPTOR_INDEX_FILE_PATH) SED_BEFORE_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITH_EXTERN_STRING) SED_AFTER_STRING=$(ITEMENCRYPTOR_INDEX_FILE_WITHOUT_EXTERN_STRING) + +_sed_types_file_remove_extern: + echo "no types file" + +_sed_types_file_add_extern: + echo "no types file" + +test_python_client_interface: + rm -rf runtimes/python/.tox + python3 -m tox -c runtimes/python -e client + +test_python_resource_interface: + rm -rf runtimes/python/.tox + python3 -m tox -c runtimes/python -e resource + +test_python_table_interface: + rm -rf runtimes/python/.tox + python3 -m tox -c runtimes/python -e table diff --git a/TestVectors/runtimes/python/.gitignore b/TestVectors/runtimes/python/.gitignore new file mode 100644 index 000000000..aaf44d4cd --- /dev/null +++ b/TestVectors/runtimes/python/.gitignore @@ -0,0 +1,17 @@ +# Python build artifacts +__pycache__ +**/__pycache__ +*.pyc +src/**.egg-info/ +build +poetry.lock +**/poetry.lock +dist + +# Dafny-generated Python +**/internaldafny/generated + +# Python test artifacts +.tox +.pytest_cache + diff --git a/TestVectors/runtimes/python/README.md b/TestVectors/runtimes/python/README.md new file mode 100644 index 000000000..6d46a446c --- /dev/null +++ b/TestVectors/runtimes/python/README.md @@ -0,0 +1,24 @@ +The Python AWS DBESDK for DynamoDB has the following encrypted interfaces for boto3 clients: + +- `EncryptedClient` + - TestVectors test through `client/` +- `EncryptedPaginator` + - Can't write items; will not test via TestVectors +- `EncryptedResource` + - TestVectors test through `resource/` +- `EncryptedTable` + - TestVectors test through `table/` +- `EncryptedTablesManager` + - Can't write items by itself; provides EncryptedTables which are tested via `table/` + +The Python AWS DBESDK for DynamoDB's `ItemEncryptor` interface provides the following APIs: + +- encrypt_python_item / decrypt_python_item + - Standard dictionary JSON; e.g. `{"key": "value"}` + - Tested explicitly via `test/resource/` and `test/table` calling `CreateWrappedDictItemEncryptor` and calling its operations +- encrypt_dynamodb_item / decrypt_dynamodb_item + - DynamoDB JSON; e.g. `{"key": {"S": "value"}}` + - Tested implicitly via `test/resource/` and `test/table` calling `CreateWrappedDictItemEncryptor`. Calls to the dict-formatted APIs pass through the DynamoDB-formatted APIs. +- encrypt_item / decrypt_item + - DBESDK EncryptItemInput; e.g. `EncryptItemInput({"key": {"S": "value"}})` + - Tested explicitly via `test/client/` calling `CreateWrappedDynamoDbItemEncryptor` diff --git a/TestVectors/runtimes/python/pyproject.toml b/TestVectors/runtimes/python/pyproject.toml new file mode 100644 index 000000000..e1c0a23c1 --- /dev/null +++ b/TestVectors/runtimes/python/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "aws-dbesdk-dynamodb-test-vectors" +version = "0.1.0" +description = "" +authors = ["AWS Crypto Tools "] +packages = [ + { include = "aws_dbesdk_dynamodb_test_vectors", from = "src" }, +] +# Include all of the following .gitignored files in package distributions, +# even though it is not included in version control +include = ["**/internaldafny/generated/*.py"] + +[tool.poetry.dependencies] +python = "^3.11.0" +aws-dbesdk-dynamodb = { path = "../../../DynamoDbEncryption/runtimes/python", develop = false} +aws-cryptography-internal-mpl-testvectors = { path = "../../../submodules/MaterialProviders/TestVectorsAwsCryptographicMaterialProviders/runtimes/python", develop = false} + +[tool.poetry.group.test.dependencies] +pytest = "^7.4.0" +tox = "^3" + +[build-system] +requires = ["poetry-core<2.0.0"] +build-backend = "poetry.core.masonry.api"