From ac79bc8ba2b8aae122988cc7a2c8292bbf2cbdf3 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 23 Apr 2024 09:12:28 -0700 Subject: [PATCH 01/51] feat: Add MPL and hierarchy keyring example (#634) --- .coveragerc | 7 + .coveragercmpl | 1 + .github/workflows/ci_tests.yaml | 33 +- .gitignore | 5 +- buildspec.yml | 28 ++ codebuild/coverage/coverage_mpl.yml | 14 + codebuild/py311/awses_local_mpl.yml | 26 ++ codebuild/py311/examples_mpl.yml | 34 +++ codebuild/py311/integ_mpl.yml | 23 ++ codebuild/py312/awses_local_mpl.yml | 33 ++ codebuild/py312/examples_mpl.yml | 41 +++ codebuild/py312/integ_mpl.yml | 30 ++ examples/src/keyrings/__init__.py | 3 + .../example_branch_key_id_supplier.py | 41 +++ examples/src/keyrings/hierarchical_keyring.py | 204 +++++++++++++ examples/src/keyrings/module_.py | 1 + examples/src/module_.py | 1 + examples/test/keyrings/__init__.py | 3 + .../keyrings/test_i_hierarchical_keyring.py | 14 + requirements_mpl.txt | 1 + setup.py | 10 + .../internal/crypto/authentication.py | 9 +- .../internal/utils/__init__.py | 22 ++ .../materials_managers/mpl/__init__.py | 6 + .../materials_managers/mpl/cmm.py | 147 +++++++++ .../materials_managers/mpl/materials.py | 138 +++++++++ src/aws_encryption_sdk/streaming_client.py | 116 ++++++- test/mpl/README.md | 1 + test/mpl/__init__.py | 6 + .../unit/test_material_managers_mpl_cmm.py | 284 ++++++++++++++++++ .../test_material_managers_mpl_materials.py | 189 ++++++++++++ .../unit/test_crypto_authentication_signer.py | 75 ++++- test/unit/test_streaming_client_configs.py | 124 ++++++++ test/unit/test_streaming_client_mpl_import.py | 37 +++ .../test_streaming_client_stream_decryptor.py | 116 ++++++- .../test_streaming_client_stream_encryptor.py | 85 ++++++ test/unit/test_utils.py | 25 ++ test_vector_handlers/tox.ini | 5 +- tox.ini | 53 +++- 39 files changed, 1955 insertions(+), 36 deletions(-) create mode 100644 .coveragerc create mode 100644 .coveragercmpl create mode 100644 codebuild/coverage/coverage_mpl.yml create mode 100644 codebuild/py311/awses_local_mpl.yml create mode 100644 codebuild/py311/examples_mpl.yml create mode 100644 codebuild/py311/integ_mpl.yml create mode 100644 codebuild/py312/awses_local_mpl.yml create mode 100644 codebuild/py312/examples_mpl.yml create mode 100644 codebuild/py312/integ_mpl.yml create mode 100644 examples/src/keyrings/__init__.py create mode 100644 examples/src/keyrings/example_branch_key_id_supplier.py create mode 100644 examples/src/keyrings/hierarchical_keyring.py create mode 100644 examples/src/keyrings/module_.py create mode 100644 examples/src/module_.py create mode 100644 examples/test/keyrings/__init__.py create mode 100644 examples/test/keyrings/test_i_hierarchical_keyring.py create mode 100644 requirements_mpl.txt create mode 100644 src/aws_encryption_sdk/materials_managers/mpl/__init__.py create mode 100644 src/aws_encryption_sdk/materials_managers/mpl/cmm.py create mode 100644 src/aws_encryption_sdk/materials_managers/mpl/materials.py create mode 100644 test/mpl/README.md create mode 100644 test/mpl/__init__.py create mode 100644 test/mpl/unit/test_material_managers_mpl_cmm.py create mode 100644 test/mpl/unit/test_material_managers_mpl_materials.py create mode 100644 test/unit/test_streaming_client_mpl_import.py diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..8957349aa --- /dev/null +++ b/.coveragerc @@ -0,0 +1,7 @@ +# .coveragerc file when running coverage WITHOUT coverage for the MPL +# This prevents the ESDK without the MPL from considering the MPL-specific modules as "missed" coverage +[run] +omit = */aws_encryption_sdk/materials_managers/mpl/* + +[report] +omit = */aws_encryption_sdk/materials_managers/mpl/* \ No newline at end of file diff --git a/.coveragercmpl b/.coveragercmpl new file mode 100644 index 000000000..31a7b4407 --- /dev/null +++ b/.coveragercmpl @@ -0,0 +1 @@ +# .coveragerc file when running coverage WITH coverage for the MPL diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index cc5da2c09..3187b8db0 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -25,7 +25,11 @@ jobs: matrix: os: - ubuntu-latest - - windows-latest + # Windows fails due to "No module named 'Wrappers'" + # This SHOULD be fixed once Dafny generates fully-qualified import statements + # (i.e. doo files, per-package module names) + # Disable for now + # - windows-latest - macos-latest python: - 3.7 @@ -41,17 +45,40 @@ jobs: category: - local - accept + - mpllocal # These require credentials. # Enable them once we sort how to provide them. # - integ # - examples + # Append '-mpl' to some test environments. + # This suffix signals to tox to install the MPL in the test environment. + optional_mpl_dependency: + - "" + - -mpl exclude: # x86 builds are only meaningful for Windows - os: ubuntu-latest architecture: x86 - os: macos-latest architecture: x86 + # MPL is not supported on <3.11 + - python: 3.7 + optional_mpl_dependency: -mpl + - python: 3.8 + optional_mpl_dependency: -mpl + - python: 3.9 + optional_mpl_dependency: -mpl + - python: 3.10 + optional_mpl_dependency: -mpl + # mpllocal requires the MPL to be installed + - category: mpllocal + optional_mpl_dependency: "" steps: + # Support long Dafny filenames (used in MPL and DBESDK repos) + - name: Support longpaths + run: | + git config --global core.longpaths true + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: @@ -62,7 +89,7 @@ jobs: pip install --upgrade -r dev_requirements/ci-requirements.txt - name: run test env: - TOXENV: ${{ matrix.category }} + TOXENV: ${{ matrix.category }}${{ matrix.optional_mpl_dependency }} run: tox -- -vv upstream-py311: runs-on: ubuntu-latest @@ -82,5 +109,5 @@ jobs: pip install --upgrade -r dev_requirements/ci-requirements.txt - name: run test env: - TOXENV: ${{ matrix.category }} + TOXENV: ${{ matrix.category }}${{ matrix.optional_mpl_dependency }} run: tox -- -vv diff --git a/.gitignore b/.gitignore index 63097dcba..fc224adc4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,9 @@ docs/build __pycache__ *.egg-info -# Coverage.py -.coverage* +# Coverage.py, NOT .coveragerc nor .coveragercmpl +.coverage +.coverage.py # MyPy .mypy_cache diff --git a/buildspec.yml b/buildspec.yml index f92d203a0..5dbd3f2b8 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -58,30 +58,58 @@ batch: buildspec: codebuild/py311/integ.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_integ_mpl + buildspec: codebuild/py311/integ_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py311_examples buildspec: codebuild/py311/examples.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_examples_mpl + buildspec: codebuild/py311/examples_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py311_awses_latest buildspec: codebuild/py311/awses_local.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_awses_latest_mpl + buildspec: codebuild/py311/awses_local_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_integ buildspec: codebuild/py312/integ.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_integ_mpl + buildspec: codebuild/py312/integ_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_examples buildspec: codebuild/py312/examples.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_examples_mpl + buildspec: codebuild/py312/examples_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_awses_latest buildspec: codebuild/py312/awses_local.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_awses_latest_mpl + buildspec: codebuild/py312/awses_local_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: code_coverage buildspec: codebuild/coverage/coverage.yml + - identifier: code_coverage_mpl + buildspec: codebuild/coverage/coverage_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: compliance buildspec: codebuild/compliance/compliance.yml diff --git a/codebuild/coverage/coverage_mpl.yml b/codebuild/coverage/coverage_mpl.yml new file mode 100644 index 000000000..922705569 --- /dev/null +++ b/codebuild/coverage/coverage_mpl.yml @@ -0,0 +1,14 @@ +version: 0.2 + +env: + variables: + TOXENV: "mplcoverage-mpl" + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - tox diff --git a/codebuild/py311/awses_local_mpl.yml b/codebuild/py311/awses_local_mpl.yml new file mode 100644 index 000000000..859931aa3 --- /dev/null +++ b/codebuild/py311/awses_local_mpl.yml @@ -0,0 +1,26 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-awses_local-mpl" + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_API_DEPLOYMENT_ID: "xi1mwx3ttb" + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_REGION: "us-west-2" + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - tox diff --git a/codebuild/py311/examples_mpl.yml b/codebuild/py311/examples_mpl.yml new file mode 100644 index 000000000..19a5dec05 --- /dev/null +++ b/codebuild/py311/examples_mpl.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + # Run non-MPL-specific tests with the MPL installed + - tox -e py311-examples-mpl + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py311ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - tox -e py311-mplexamples-mpl + diff --git a/codebuild/py311/integ_mpl.yml b/codebuild/py311/integ_mpl.yml new file mode 100644 index 000000000..694bc0850 --- /dev/null +++ b/codebuild/py311/integ_mpl.yml @@ -0,0 +1,23 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-integ-mpl" + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - tox diff --git a/codebuild/py312/awses_local_mpl.yml b/codebuild/py312/awses_local_mpl.yml new file mode 100644 index 000000000..1d0f80319 --- /dev/null +++ b/codebuild/py312/awses_local_mpl.yml @@ -0,0 +1,33 @@ +# Runs the same tests as awses_local in an environment with the MPL installed. +# This asserts existing tests continue to pass with the MPL installed. +version: 0.2 + +env: + variables: + TOXENV: "py312-awses_local-mpl" + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_API_DEPLOYMENT_ID: "xi1mwx3ttb" + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_REGION: "us-west-2" + +phases: + install: + runtime-versions: + python: latest + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.12.0 + - pyenv local 3.12.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + - cd test_vector_handlers + - tox diff --git a/codebuild/py312/examples_mpl.yml b/codebuild/py312/examples_mpl.yml new file mode 100644 index 000000000..366222441 --- /dev/null +++ b/codebuild/py312/examples_mpl.yml @@ -0,0 +1,41 @@ +# Runs the same tests as examples in an environment with the MPL installed +# to assert existing tests continue to pass with the MPL installed. +# Then, run MPL-specific tests. +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: latest + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.12.0 + - pyenv local 3.12.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + # Run non-MPL-specific tests with the MPL installed + - tox -e py312-examples-mpl + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py311ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - tox -e py312-mplexamples-mpl diff --git a/codebuild/py312/integ_mpl.yml b/codebuild/py312/integ_mpl.yml new file mode 100644 index 000000000..e292acc57 --- /dev/null +++ b/codebuild/py312/integ_mpl.yml @@ -0,0 +1,30 @@ +# Runs the same tests as integ in an environment with the MPL installed. +# This asserts existing tests continue to pass with the MPL installed. +version: 0.2 + +env: + variables: + TOXENV: "py312-integ-mpl" + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: latest + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.12.0 + - pyenv local 3.12.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + - tox diff --git a/examples/src/keyrings/__init__.py b/examples/src/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/src/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/src/keyrings/example_branch_key_id_supplier.py b/examples/src/keyrings/example_branch_key_id_supplier.py new file mode 100644 index 000000000..7b390cdda --- /dev/null +++ b/examples/src/keyrings/example_branch_key_id_supplier.py @@ -0,0 +1,41 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Example implementation of a branch key ID supplier.""" + +from aws_cryptographic_materialproviders.mpl.models import GetBranchKeyIdInput, GetBranchKeyIdOutput +from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier +from typing import Dict + + +class ExampleBranchKeyIdSupplier(IBranchKeyIdSupplier): + """Example implementation of a branch key ID supplier.""" + + branch_key_id_for_tenant_A: str + branch_key_id_for_tenant_B: str + + def __init__(self, tenant_1_id, tenant_2_id): + """Example constructor for a branch key ID supplier.""" + self.branch_key_id_for_tenant_A = tenant_1_id + self.branch_key_id_for_tenant_B = tenant_2_id + + def get_branch_key_id( + self, + param: GetBranchKeyIdInput + ) -> GetBranchKeyIdOutput: + """Returns branch key ID from the tenant ID in input's encryption context.""" + encryption_context: Dict[str, str] = param.encryption_context + + if b"tenant" not in encryption_context: + raise ValueError("EncryptionContext invalid, does not contain expected tenant key value pair.") + + tenant_key_id: str = encryption_context.get(b"tenant") + branch_key_id: str + + if tenant_key_id == b"TenantA": + branch_key_id = self.branch_key_id_for_tenant_A + elif tenant_key_id == b"TenantB": + branch_key_id = self.branch_key_id_for_tenant_B + else: + raise ValueError(f"Item does not contain valid tenant ID: {tenant_key_id=}") + + return GetBranchKeyIdOutput(branch_key_id=branch_key_id) diff --git a/examples/src/keyrings/hierarchical_keyring.py b/examples/src/keyrings/hierarchical_keyring.py new file mode 100644 index 000000000..aa87485f9 --- /dev/null +++ b/examples/src/keyrings/hierarchical_keyring.py @@ -0,0 +1,204 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Example showing basic encryption and decryption of a value already in memory.""" +import sys + +import boto3 +# Ignore missing MPL for pylint, but the MPL is required for this example +# noqa pylint: disable=import-error +from aws_cryptographic_materialproviders.keystore import KeyStore +from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig +from aws_cryptographic_materialproviders.keystore.models import CreateKeyInput, KMSConfigurationKmsKeyArn +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CacheTypeDefault, + CreateAwsKmsHierarchicalKeyringInput, + DefaultCache, +) +from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier, IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + +from .example_branch_key_id_supplier import ExampleBranchKeyIdSupplier + +module_root_dir = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(module_root_dir) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + key_store_table_name: str, + logical_key_store_name: str, + kms_key_id: str +): + """Creates a hierarchical keyring using the provided resources, then encrypts and decrypts a string with it.""" + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create boto3 clients for DynamoDB and KMS. + ddb_client = boto3.client('dynamodb', region_name="us-west-2") + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Configure your KeyStore resource. + # This SHOULD be the same configuration that you used + # to initially create and populate your KeyStore. + keystore: KeyStore = KeyStore( + config=KeyStoreConfig( + ddb_client=ddb_client, + ddb_table_name=key_store_table_name, + logical_key_store_name=logical_key_store_name, + kms_client=kms_client, + kms_configuration=KMSConfigurationKmsKeyArn( + value=kms_key_id + ), + ) + ) + + # 4. Call CreateKey to create two new active branch keys + branch_key_id_A: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier + branch_key_id_B: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier + + # 5. Create a branch key supplier that maps the branch key id to a more readable format + branch_key_id_supplier: IBranchKeyIdSupplier = ExampleBranchKeyIdSupplier( + tenant_1_id=branch_key_id_A, + tenant_2_id=branch_key_id_B, + ) + + # 6. Create the Hierarchical Keyring. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id_supplier=branch_key_id_supplier, + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input + ) + + # 7. Create encryption context for both tenants. + # The Branch Key Id supplier uses the encryption context to determine which branch key id will + # be used to encrypt data. + + # Create encryption context for TenantA + encryption_context_A: Dict[str, str] = { + "tenant": "TenantA", + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # Create encryption context for TenantB + encryption_context_B: Dict[str, str] = { + "tenant": "TenantB", + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 8. Encrypt the data for encryptionContextA & encryptionContextB + ciphertext_A, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=hierarchical_keyring, + encryption_context=encryption_context_A + ) + ciphertext_B, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=hierarchical_keyring, + encryption_context=encryption_context_B + ) + + # 9. To attest that TenantKeyB cannot decrypt a message written by TenantKeyA, + # let's construct more restrictive hierarchical keyrings. + keyring_input_A: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id=branch_key_id_A, + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + hierarchical_keyring_A: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input_A + ) + + keyring_input_B: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id=branch_key_id_B, + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + hierarchical_keyring_B: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input_B + ) + + # 10. Demonstrate that data encrypted by one tenant's key + # cannot be decrypted with by a keyring specific to another tenant. + + # Keyring with tenant B's branch key cannot decrypt data encrypted with tenant A's branch key + # This will fail and raise a AWSEncryptionSDKClientError, which we swallow ONLY for demonstration purposes. + try: + client.decrypt( + source=ciphertext_A, + keyring=hierarchical_keyring_B + ) + except AWSEncryptionSDKClientError: + pass + + # Keyring with tenant A's branch key cannot decrypt data encrypted with tenant B's branch key. + # This will fail and raise a AWSEncryptionSDKClientError, which we swallow ONLY for demonstration purposes. + try: + client.decrypt( + source=ciphertext_B, + keyring=hierarchical_keyring_A + ) + except AWSEncryptionSDKClientError: + pass + + # 10. Demonstrate that data encrypted by one tenant's branch key can be decrypted by that tenant, + # and that the decrypted data matches the input data. + plaintext_bytes_A, _ = client.decrypt( + source=ciphertext_A, + keyring=hierarchical_keyring_A + ) + assert plaintext_bytes_A == EXAMPLE_DATA + plaintext_bytes_B, _ = client.decrypt( + source=ciphertext_B, + keyring=hierarchical_keyring_B + ) + assert plaintext_bytes_B == EXAMPLE_DATA diff --git a/examples/src/keyrings/module_.py b/examples/src/keyrings/module_.py new file mode 100644 index 000000000..3e8d3062a --- /dev/null +++ b/examples/src/keyrings/module_.py @@ -0,0 +1 @@ +"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/src/module_.py b/examples/src/module_.py new file mode 100644 index 000000000..3e8d3062a --- /dev/null +++ b/examples/src/module_.py @@ -0,0 +1 @@ +"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/test/keyrings/__init__.py b/examples/test/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/keyrings/test_i_hierarchical_keyring.py b/examples/test/keyrings/test_i_hierarchical_keyring.py new file mode 100644 index 000000000..4cae478d7 --- /dev/null +++ b/examples/test/keyrings/test_i_hierarchical_keyring.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Unit test suite for the hierarchical keyring example.""" +import pytest + +from ...src.keyrings.hierarchical_keyring import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + key_store_table_name = "KeyStoreDdbTable" + key_arn = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126" + encrypt_and_decrypt_with_keyring(key_store_table_name, key_store_table_name, key_arn) diff --git a/requirements_mpl.txt b/requirements_mpl.txt new file mode 100644 index 000000000..209e10f2c --- /dev/null +++ b/requirements_mpl.txt @@ -0,0 +1 @@ +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/setup.py b/setup.py index 7cc111bac..0615a43c7 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,14 @@ def get_requirements(): keywords="aws-encryption-sdk aws kms encryption", license="Apache License 2.0", install_requires=get_requirements(), + # pylint: disable=fixme + # TODO: Point at PyPI once MPL is released. + # This blocks releasing ESDK-Python MPL integration. + extras_require={ + "MPL": ["aws-cryptographic-material-providers @" \ + "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ + "lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + }, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -49,6 +57,8 @@ def get_requirements(): "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Security", "Topic :: Security :: Cryptography", diff --git a/src/aws_encryption_sdk/internal/crypto/authentication.py b/src/aws_encryption_sdk/internal/crypto/authentication.py index f90ac77e0..d7ff35278 100644 --- a/src/aws_encryption_sdk/internal/crypto/authentication.py +++ b/src/aws_encryption_sdk/internal/crypto/authentication.py @@ -68,7 +68,7 @@ class Signer(_PrehashingAuthenticator): """ @classmethod - def from_key_bytes(cls, algorithm, key_bytes): + def from_key_bytes(cls, algorithm, key_bytes, encoding=serialization.Encoding.DER): """Builds a `Signer` from an algorithm suite and a raw signing key. :param algorithm: Algorithm on which to base signer @@ -76,7 +76,12 @@ def from_key_bytes(cls, algorithm, key_bytes): :param bytes key_bytes: Raw signing key :rtype: aws_encryption_sdk.internal.crypto.Signer """ - key = serialization.load_der_private_key(data=key_bytes, password=None, backend=default_backend()) + if encoding == serialization.Encoding.DER: + key = serialization.load_der_private_key(data=key_bytes, password=None, backend=default_backend()) + elif encoding == serialization.Encoding.PEM: + key = serialization.load_pem_private_key(data=key_bytes, password=None, backend=default_backend()) + else: + raise ValueError(f"Unsupported encoding for Signer: {encoding}") return cls(algorithm, key) def key_bytes(self): diff --git a/src/aws_encryption_sdk/internal/utils/__init__.py b/src/aws_encryption_sdk/internal/utils/__init__.py index dac38ac73..b08121281 100644 --- a/src/aws_encryption_sdk/internal/utils/__init__.py +++ b/src/aws_encryption_sdk/internal/utils/__init__.py @@ -163,3 +163,25 @@ def source_data_key_length_check(source_data_key, algorithm): actual=len(source_data_key.data_key), required=algorithm.kdf_input_len ) ) + + +def exactly_one_arg_is_not_none(*args): + """ + Helper function for internal ESDK logic. + Returns `True` if exactly one item in the provided arguments is not `None`. + Returns `False` otherwise. + + :param args: Input arguments to check + :returns: `True` if exactly one item in the provided arguments is not `None`; `False` otherwise + """ + # Have not found any `not None` + found_one = False + for arg in args: + if arg is not None: + if found_one is False: + # Have not already found a `not None`, found a `not None` => only one `not None` (so far) + found_one = True + else: + # Already found a `not None`, found another `not None` => not exactly one `not None` + return False + return found_one diff --git a/src/aws_encryption_sdk/materials_managers/mpl/__init__.py b/src/aws_encryption_sdk/materials_managers/mpl/__init__.py new file mode 100644 index 000000000..be75f3566 --- /dev/null +++ b/src/aws_encryption_sdk/materials_managers/mpl/__init__.py @@ -0,0 +1,6 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Modules related to the MPL's materials managers interfaces. + +The aws-cryptographic-materials-library MUST be installed to use these modules. +""" diff --git a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py new file mode 100644 index 000000000..880e37203 --- /dev/null +++ b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py @@ -0,0 +1,147 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Retrieves encryption/decryption materials from the MPL and interfaces them to EDK components. + +The aws-cryptographic-materials-library MUST be installed to use this module. +""" +# pylint should pass even if the MPL isn't installed +# Also thinks these imports aren't used if it can't import them +# noqa pylint: disable=import-error,unused-import +from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException +from aws_cryptographic_materialproviders.mpl.models import ( + AlgorithmSuiteIdESDK as MPL_AlgorithmSuiteIdESDK, + CommitmentPolicyESDK as MPL_CommitmentPolicyESDK, + DecryptMaterialsInput as MPL_DecryptMaterialsInput, + DecryptMaterialsOutput as MPL_DecryptMaterialsOutput, + EncryptedDataKey as MPL_EncryptedDataKey, + GetEncryptionMaterialsInput as MPL_GetEncryptionMaterialsInput, + GetEncryptionMaterialsOutput as MPL_GetEncryptionMaterialsOutput, +) +from aws_cryptographic_materialproviders.mpl.references import ( + ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, +) +# noqa pylint: enable=import-error,unused-import +# pylint and isort disagree on where this should go. Choose isort and disable pylint for this. +from typing import List # noqa pylint: disable=wrong-import-order + +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError +from aws_encryption_sdk.identifiers import CommitmentPolicy +from aws_encryption_sdk.materials_managers import DecryptionMaterialsRequest, EncryptionMaterialsRequest +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager +from aws_encryption_sdk.materials_managers.mpl.materials import DecryptionMaterialsFromMPL, EncryptionMaterialsFromMPL +from aws_encryption_sdk.structures import EncryptedDataKey as Native_EncryptedDataKey + + +class CryptoMaterialsManagerFromMPL(CryptoMaterialsManager): + """ + In instances where encryption materials are provided by an implementation of the MPL's + `aws_cryptographic_materialproviders.mpl.references.MPL_ICryptographicMaterialsManager`, + this maps the ESDK-Python CMM interfaces to the MPL CMM. + """ + + mpl_cmm: 'MPL_ICryptographicMaterialsManager' + + def __init__( + self, + mpl_cmm: 'MPL_ICryptographicMaterialsManager' + ): + """ + Create CryptoMaterialsManagerFromMPL. + :param mpl_cmm: Underlying MPL cryptographic materials manager + """ + if isinstance(mpl_cmm, MPL_ICryptographicMaterialsManager): + self.mpl_cmm = mpl_cmm + else: + raise ValueError(f"Invalid CMM passed to CryptoMaterialsManagerFromMPL. cmm: {mpl_cmm}") + + def get_encryption_materials( + self, + request: EncryptionMaterialsRequest + ) -> EncryptionMaterialsFromMPL: + """ + Returns an EncryptionMaterialsHandler for the configured CMM. + :param request: Request for encryption materials + """ + try: + mpl_input: MPL_GetEncryptionMaterialsInput = \ + CryptoMaterialsManagerFromMPL._native_to_mpl_get_encryption_materials( + request + ) + mpl_output: MPL_GetEncryptionMaterialsOutput = self.mpl_cmm.get_encryption_materials(mpl_input) + return EncryptionMaterialsFromMPL(mpl_output.encryption_materials) + except AwsCryptographicMaterialProvidersException as mpl_exception: + # Wrap MPL error into the ESDK error type + # so customers only have to catch ESDK error types. + raise AWSEncryptionSDKClientError(mpl_exception) + + @staticmethod + def _native_to_mpl_get_encryption_materials( + request: EncryptionMaterialsRequest + ) -> 'MPL_GetEncryptionMaterialsInput': + commitment_policy = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy( + request.commitment_policy + ) + output: MPL_GetEncryptionMaterialsInput = MPL_GetEncryptionMaterialsInput( + encryption_context=request.encryption_context, + commitment_policy=commitment_policy, + max_plaintext_length=request.plaintext_length, + ) + return output + + @staticmethod + def _native_to_mpl_commmitment_policy( + native_commitment_policy: CommitmentPolicy + ) -> 'MPL_CommitmentPolicyESDK': + if native_commitment_policy == CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT: + return MPL_CommitmentPolicyESDK(value="FORBID_ENCRYPT_ALLOW_DECRYPT") + elif native_commitment_policy == CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT: + return MPL_CommitmentPolicyESDK(value="REQUIRE_ENCRYPT_ALLOW_DECRYPT") + elif native_commitment_policy == CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT: + return MPL_CommitmentPolicyESDK(value="REQUIRE_ENCRYPT_REQUIRE_DECRYPT") + else: + raise ValueError(f"Invalid native_commitment_policy: {native_commitment_policy}") + + def decrypt_materials( + self, + request: DecryptionMaterialsRequest + ) -> DecryptionMaterialsFromMPL: + """ + Returns a DecryptionMaterialsFromMPL for the configured CMM. + :param request: Request for decryption materials + """ + try: + mpl_input: 'MPL_DecryptMaterialsInput' = \ + CryptoMaterialsManagerFromMPL._create_mpl_decrypt_materials_input_from_request(request) + mpl_output: 'MPL_DecryptMaterialsOutput' = self.mpl_cmm.decrypt_materials(mpl_input) + return DecryptionMaterialsFromMPL(mpl_output.decryption_materials) + except AwsCryptographicMaterialProvidersException as mpl_exception: + # Wrap MPL error into the ESDK error type + # so customers only have to catch ESDK error types. + raise AWSEncryptionSDKClientError(mpl_exception) + + @staticmethod + def _native_algorithm_id_to_mpl_algorithm_id(native_algorithm_id: str) -> 'MPL_AlgorithmSuiteIdESDK': + # MPL algorithm suite ID = hexstr(native_algorithm_id) padded to 4 digits post-`x`. + return MPL_AlgorithmSuiteIdESDK(f"{native_algorithm_id:#0{6}x}") + + @staticmethod + def _create_mpl_decrypt_materials_input_from_request( + request: DecryptionMaterialsRequest + ) -> 'MPL_DecryptMaterialsInput': + key_blob_list: List[Native_EncryptedDataKey] = request.encrypted_data_keys + list_edks = [MPL_EncryptedDataKey( + key_provider_id=key_blob.key_provider.provider_id, + key_provider_info=key_blob.key_provider.key_info, + ciphertext=key_blob.encrypted_data_key, + ) for key_blob in key_blob_list] + output: MPL_DecryptMaterialsInput = MPL_DecryptMaterialsInput( + algorithm_suite_id=CryptoMaterialsManagerFromMPL._native_algorithm_id_to_mpl_algorithm_id( + request.algorithm.algorithm_id + ), + commitment_policy=CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy( + request.commitment_policy + ), + encrypted_data_keys=list_edks, + encryption_context=request.encryption_context, + ) + return output diff --git a/src/aws_encryption_sdk/materials_managers/mpl/materials.py b/src/aws_encryption_sdk/materials_managers/mpl/materials.py new file mode 100644 index 000000000..dfd1bd6fc --- /dev/null +++ b/src/aws_encryption_sdk/materials_managers/mpl/materials.py @@ -0,0 +1,138 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Provides encryption/decryption materials from an underlying materials provider from the MPL. + +The aws-cryptographic-materials-library MUST be installed to use this module. +""" +# pylint should pass even if the MPL isn't installed +# noqa pylint: disable=import-error +from aws_cryptographic_materialproviders.mpl.models import ( + DecryptionMaterials as MPL_DecryptionMaterials, + EncryptedDataKey as MPL_EncryptedDataKey, + EncryptionMaterials as MPL_EncryptionMaterials, +) +# pylint and isort disagree on where this should go. Choose isort and disable pylint for this. +from typing import Dict, List, Set # noqa pylint: disable=wrong-import-order + +from aws_encryption_sdk.identifiers import Algorithm, AlgorithmSuite +from aws_encryption_sdk.materials_managers import ( + DecryptionMaterials as Native_DecryptionMaterials, + EncryptionMaterials as Native_EncryptionMaterials, +) +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey as Native_EncryptedDataKey, MasterKeyInfo + + +def _mpl_algorithm_id_to_native_algorithm_id(mpl_algorithm_id: str) -> int: + # MPL algorithm suite ID == hex(native algorithm suite ID) + return int(mpl_algorithm_id, 16) + + +class EncryptionMaterialsFromMPL(Native_EncryptionMaterials): + """ + In instances where encryption materials are be provided by + the MPL's `aws_cryptographic_materialproviders.mpl.models.EncryptionMaterials`, + this maps the ESDK interfaces to the underlying MPL materials. + """ + + mpl_materials: 'MPL_EncryptionMaterials' + + def __init__( + self, + mpl_materials: 'MPL_EncryptionMaterials' + ): + """ + Create EncryptionMaterialsFromMPL. + :param materials: Underlying encryption materials + """ + if isinstance(mpl_materials, MPL_EncryptionMaterials): + self.mpl_materials = mpl_materials + else: + raise ValueError("Invalid EncryptionMaterials passed to EncryptionMaterialsFromMPL. " + f"materials: {mpl_materials}") + + @property + def algorithm(self) -> Algorithm: + """Materials' native Algorithm.""" + return AlgorithmSuite.get_by_id( + _mpl_algorithm_id_to_native_algorithm_id( + self.mpl_materials.algorithm_suite.id.value + ) + ) + + @property + def encryption_context(self) -> Dict[str, str]: + """Materials' encryption context.""" + return self.mpl_materials.encryption_context + + @property + def encrypted_data_keys(self) -> List[Native_EncryptedDataKey]: + """Materials' encrypted data keys.""" + mpl_edk_list: List[MPL_EncryptedDataKey] = self.mpl_materials.encrypted_data_keys + key_blob_list: Set[Native_EncryptedDataKey] = {Native_EncryptedDataKey( + key_provider=MasterKeyInfo( + provider_id=mpl_edk.key_provider_id, + key_info=mpl_edk.key_provider_info, + ), + encrypted_data_key=mpl_edk.ciphertext, + ) for mpl_edk in mpl_edk_list} + return key_blob_list + + @property + def data_encryption_key(self) -> DataKey: + """Materials' data encryption key.""" + mpl_dek = self.mpl_materials.plaintext_data_key + return DataKey( + # key_provider is unused, but the return type is DataKey + key_provider=MasterKeyInfo( + provider_id="", + key_info=b'' + ), + data_key=mpl_dek, + encrypted_data_key=b'', # No encrypted DEK + ) + + @property + def signing_key(self) -> bytes: + """Materials' signing key.""" + return self.mpl_materials.signing_key + + +class DecryptionMaterialsFromMPL(Native_DecryptionMaterials): + """ + In instances where decryption materials are be provided by + the MPL's `aws_cryptographic_materialproviders.mpl.models.DecryptionMaterials`, + this maps the ESDK interfaces to the underlying MPL materials. + """ + + mpl_materials: 'MPL_DecryptionMaterials' + + def __init__( + self, + mpl_materials: 'MPL_DecryptionMaterials' + ): + """ + Create DecryptionMaterialsFromMPL. + :param materials: Underlying decryption materials + """ + if isinstance(mpl_materials, MPL_DecryptionMaterials): + self.mpl_materials = mpl_materials + else: + raise ValueError(f"Invalid DecryptionMaterials passed to DecryptionMaterialsFromMPL.\ + materials: {mpl_materials}") + + @property + def data_key(self) -> DataKey: + """Materials' data key.""" + return DataKey( + key_provider=MasterKeyInfo( + provider_id="", + key_info=b'' + ), + data_key=self.mpl_materials.plaintext_data_key, + encrypted_data_key=b'', + ) + + @property + def verification_key(self) -> bytes: + """Materials' verification key.""" + return self.mpl_materials.verification_key diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 1119cb740..5bf953244 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -14,6 +14,7 @@ from __future__ import division import abc +import base64 import hmac import io import logging @@ -21,6 +22,7 @@ import attr import six +from cryptography.hazmat.primitives import serialization import aws_encryption_sdk.internal.utils from aws_encryption_sdk.exceptions import ( @@ -56,6 +58,7 @@ serialize_non_framed_close, serialize_non_framed_open, ) +from aws_encryption_sdk.internal.utils import exactly_one_arg_is_not_none from aws_encryption_sdk.internal.utils.commitment import ( validate_commitment_policy_on_decrypt, validate_commitment_policy_on_encrypt, @@ -67,6 +70,22 @@ from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager from aws_encryption_sdk.structures import MessageHeader +try: + # pylint should pass even if the MPL isn't installed + # noqa pylint: disable=import-error + from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException + from aws_cryptographic_materialproviders.mpl.models import CreateDefaultCryptographicMaterialsManagerInput + from aws_cryptographic_materialproviders.mpl.references import IKeyring + _HAS_MPL = True + + # Import internal ESDK modules that depend on the MPL + from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL + +except ImportError: + _HAS_MPL = False + _LOGGER = logging.getLogger(__name__) @@ -113,6 +132,11 @@ class _ClientConfig(object): # pylint: disable=too-many-instance-attributes key_provider = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(MasterKeyProvider)) ) + if _HAS_MPL: + # Keyrings are only available if the MPL is installed in the runtime + keyring = attr.ib( + hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(IKeyring)) + ) source_length = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)) ) @@ -120,8 +144,39 @@ class _ClientConfig(object): # pylint: disable=too-many-instance-attributes hash=True, default=LINE_LENGTH, validator=attr.validators.instance_of(six.integer_types) ) # DEPRECATED: Value is no longer configurable here. Parameter left here to avoid breaking consumers. - def __attrs_post_init__(self): - """Normalize inputs to crypto material manager.""" + def _has_mpl_attrs_post_init(self): + """If the MPL is present in the runtime, perform MPL-specific post-init logic + to validate the new object has a valid state. + """ + if not exactly_one_arg_is_not_none(self.materials_manager, self.key_provider, self.keyring): + raise TypeError("Exactly one of keyring, materials_manager, or key_provider must be provided") + if self.materials_manager is None: + if self.key_provider is not None: + # No CMM, provided legacy native `key_provider` => create legacy native DefaultCryptoMaterialsManager + self.materials_manager = DefaultCryptoMaterialsManager( + master_key_provider=self.key_provider + ) + elif self.keyring is not None: + try: + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + cmm = mat_prov.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=self.keyring + ) + ) + cmm_handler: CryptoMaterialsManager = CryptoMaterialsManagerFromMPL(cmm) + self.materials_manager = cmm_handler + except AwsCryptographicMaterialProvidersException as mpl_exception: + # Wrap MPL error into the ESDK error type + # so customers only have to catch ESDK error types. + raise AWSEncryptionSDKClientError(mpl_exception) + + def _no_mpl_attrs_post_init(self): + """If the MPL is NOT present in the runtime, perform post-init logic + to validate the new object has a valid state. + """ both_cmm_and_mkp_defined = self.materials_manager is not None and self.key_provider is not None neither_cmm_nor_mkp_defined = self.materials_manager is None and self.key_provider is None @@ -130,6 +185,13 @@ def __attrs_post_init__(self): if self.materials_manager is None: self.materials_manager = DefaultCryptoMaterialsManager(master_key_provider=self.key_provider) + def __attrs_post_init__(self): + """Normalize inputs to crypto material manager.""" + if _HAS_MPL: + self._has_mpl_attrs_post_init() + else: + self._no_mpl_attrs_post_init() + class _EncryptionStream(io.IOBase): """Parent class for StreamEncryptor and StreamDecryptor classes. @@ -343,6 +405,10 @@ class EncryptorConfig(_ClientConfig): :param key_provider: `MasterKeyProvider` from which to obtain data keys for encryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + which handles encryption and decryption + :type keyring: + aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -394,6 +460,10 @@ class StreamEncryptor(_EncryptionStream): # pylint: disable=too-many-instance-a :param key_provider: `MasterKeyProvider` from which to obtain data keys for encryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + which handles encryption and decryption + :type keyring: + aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -480,9 +550,18 @@ def _prep_message(self): if self._encryption_materials.signing_key is None: self.signer = None else: - self.signer = Signer.from_key_bytes( - algorithm=self._encryption_materials.algorithm, key_bytes=self._encryption_materials.signing_key - ) + # MPL verification key is PEM bytes, not DER bytes. + # If the underlying CMM is from the MPL, load PEM bytes. + if (_HAS_MPL + and isinstance(self.config.materials_manager, CryptoMaterialsManagerFromMPL)): + self.signer = Signer.from_key_bytes( + algorithm=self._encryption_materials.algorithm, key_bytes=self._encryption_materials.signing_key, + encoding=serialization.Encoding.PEM, + ) + else: + self.signer = Signer.from_key_bytes( + algorithm=self._encryption_materials.algorithm, key_bytes=self._encryption_materials.signing_key + ) aws_encryption_sdk.internal.utils.validate_frame_length( frame_length=self.config.frame_length, algorithm=self._encryption_materials.algorithm ) @@ -729,11 +808,15 @@ class DecryptorConfig(_ClientConfig): :param source: Source data to encrypt or decrypt :type source: str, bytes, io.IOBase, or file :param materials_manager: `CryptoMaterialsManager` from which to obtain cryptographic materials - (either `materials_manager` or `key_provider` required) + (either `keyring`, `materials_manager` or `key_provider` required) :type materials_manager: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager :param key_provider: `MasterKeyProvider` from which to obtain data keys for decryption - (either `materials_manager` or `key_provider` required) + (either `keyring`, `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + which handles encryption and decryption + :type keyring: + aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -770,6 +853,10 @@ class StreamDecryptor(_EncryptionStream): # pylint: disable=too-many-instance-a :param key_provider: `MasterKeyProvider` from which to obtain data keys for decryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + which handles encryption and decryption + :type keyring: + aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -831,9 +918,18 @@ def _read_header(self): if decryption_materials.verification_key is None: self.verifier = None else: - self.verifier = Verifier.from_key_bytes( - algorithm=header.algorithm, key_bytes=decryption_materials.verification_key - ) + # MPL verification key is NOT key bytes; it is bytes of the compressed point. + # If the underlying CMM is from the MPL, load bytes from encoded point. + if (_HAS_MPL + and isinstance(self.config.materials_manager, CryptoMaterialsManagerFromMPL)): + self.verifier = Verifier.from_encoded_point( + algorithm=header.algorithm, + encoded_point=base64.b64encode(decryption_materials.verification_key) + ) + else: + self.verifier = Verifier.from_key_bytes( + algorithm=header.algorithm, key_bytes=decryption_materials.verification_key + ) if self.verifier is not None: self.verifier.update(raw_header) diff --git a/test/mpl/README.md b/test/mpl/README.md new file mode 100644 index 000000000..7ae7134d0 --- /dev/null +++ b/test/mpl/README.md @@ -0,0 +1 @@ +Tests in this directory REQUIRE the [aws-cryptographic-material-providers](https://github.com/aws/aws-cryptographic-material-providers-library) library to execute. \ No newline at end of file diff --git a/test/mpl/__init__.py b/test/mpl/__init__.py new file mode 100644 index 000000000..79522d342 --- /dev/null +++ b/test/mpl/__init__.py @@ -0,0 +1,6 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Module testing components that use the MPL. + +The aws-cryptographic-materials-library MUST be installed to run tests in this module. +""" diff --git a/test/mpl/unit/test_material_managers_mpl_cmm.py b/test/mpl/unit/test_material_managers_mpl_cmm.py new file mode 100644 index 000000000..80d6f00ee --- /dev/null +++ b/test/mpl/unit/test_material_managers_mpl_cmm.py @@ -0,0 +1,284 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Unit test suite to validate aws_encryption_sdk.materials_managers.mpl.cmm logic. + +The aws-cryptographic-materials-library MUST be installed to run tests in this module. +""" + +import pytest +from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException +from aws_cryptographic_materialproviders.mpl.models import ( + AlgorithmSuiteIdESDK as MPL_AlgorithmSuiteIdESDK, + CommitmentPolicyESDK as MPL_CommitmentPolicyESDK, + DecryptionMaterials as MPL_DecryptionMaterials, + DecryptMaterialsInput as MPL_DecryptMaterialsInput, + EncryptionMaterials as MPL_EncryptionMaterials, + GetEncryptionMaterialsInput as MPL_GetEncryptionMaterialsInput, + GetEncryptionMaterialsOutput as MPL_GetEncryptionMaterialsOutput, +) +from aws_cryptographic_materialproviders.mpl.references import ( + ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, +) +from mock import MagicMock, patch + +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError +from aws_encryption_sdk.identifiers import CommitmentPolicy +from aws_encryption_sdk.materials_managers import DecryptionMaterialsRequest, EncryptionMaterialsRequest +from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL +from aws_encryption_sdk.materials_managers.mpl.materials import DecryptionMaterialsFromMPL, EncryptionMaterialsFromMPL +from aws_encryption_sdk.structures import EncryptedDataKey as Native_EncryptedDataKey + +pytestmark = [pytest.mark.unit, pytest.mark.local] + + +mock_encryption_materials_request = MagicMock(__class__=EncryptionMaterialsRequest) +mock_decryption_materials_request = MagicMock(__class__=DecryptionMaterialsRequest) + + +mock_mpl_cmm = MagicMock(__class__=MPL_ICryptographicMaterialsManager) +mock_mpl_encryption_materials = MagicMock(__class__=MPL_EncryptionMaterials) +mock_mpl_decrypt_materials = MagicMock(__class__=MPL_DecryptionMaterials) + + +mock_edk = MagicMock(__class__=Native_EncryptedDataKey) +mock_mpl_key_provider_id = MagicMock(__class__=str) +mock_edk.key_provider.provider_id = mock_mpl_key_provider_id +mock_mpl_key_provider_info = MagicMock(__class__=bytes) +mock_edk.key_provider.key_info = mock_mpl_key_provider_info +mock_mpl_encrypted_data_key = MagicMock(__class__=bytes) +mock_edk.encrypted_data_key = mock_mpl_encrypted_data_key + + +def test_GIVEN_valid_mpl_cmm_WHEN_create_CryptoMaterialsManagerFromMPL_THEN_return_new_CryptoMaterialsManagerFromMPL(): + # Given: valid mpl_cmm + # When: create new CryptoMaterialsManagerFromMPL + mpl_cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mock_mpl_cmm) + # Then: CryptoMaterialsManagerFromMPL is valid + assert mpl_cmm.mpl_cmm == mock_mpl_cmm + + +def test_GIVEN_invalid_mpl_cmm_WHEN_create_CryptoMaterialsManagerFromMPL_THEN_raise_ValueError(): + # Then: raises ValueError + with pytest.raises(ValueError): + # Given: invalid mpl_cmm + # When: create new CryptoMaterialsManagerFromMPL + CryptoMaterialsManagerFromMPL(mpl_cmm="not a valid mpl_cmm") + + +@patch.object(mock_mpl_cmm, "get_encryption_materials") +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_get_encryption_materials") +def test_GIVEN_valid_request_WHEN_get_encryption_materials_THEN_return_EncryptionMaterialsFromMPL( + mock_native_to_mpl_get_encryption_materials, + mock_get_encryption_materials, +): + + # Given: _native_to_mpl_get_encryption_materials creates a MPL_GetEncryptionMaterialsInput + mock_get_encryption_materials_input = MagicMock(__class__=MPL_GetEncryptionMaterialsInput) + mock_native_to_mpl_get_encryption_materials.return_value = mock_get_encryption_materials_input + + # Given: mpl_cmm.get_encryption_materials returns mock MPL encryption materials + mock_get_encryption_materials_output = MagicMock(__class__=MPL_GetEncryptionMaterialsOutput) + mock_get_encryption_materials_output.encryption_materials = mock_mpl_encryption_materials + mock_get_encryption_materials.return_value = mock_get_encryption_materials_output + + # When: get_encryption_materials + cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mock_mpl_cmm) + output = cmm.get_encryption_materials(mock_encryption_materials_request) + + # Then: + # Verify cmm returns EncryptionMaterialsFromMPL + assert isinstance(output, EncryptionMaterialsFromMPL) + # Verify returned EncryptionMaterialsHandler uses the output of `get_encryption_materials` + assert output.mpl_materials == mock_mpl_encryption_materials + # Verify we actually called `get_encryption_materials` + mock_mpl_cmm.get_encryption_materials.assert_called_once_with(mock_get_encryption_materials_input) + + +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_commmitment_policy") +def test_GIVEN_mpl_cmm_raises_MPLException_WHEN_get_encryption_materials_THEN_raise_ESDKException( + _ +): + # Then: Raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # Given: mpl_cmm.get_encryption_materials raises MPL exception + with patch.object(mock_mpl_cmm, "get_encryption_materials", + side_effect=AwsCryptographicMaterialProvidersException("any")): + # When: get_encryption_materials + cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mock_mpl_cmm) + cmm.get_encryption_materials(mock_encryption_materials_request) + + +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_commmitment_policy") +def test_GIVEN_valid_mpl_commitment_policy_WHEN_native_to_mpl_get_encryption_materials_THEN_returns_MPL_GetEncryptionMaterialsInput( # noqa: E501 + mock_mpl_commitment_policy +): + # Given: commitment policy is some MPL ESDK commitment policy + mock_commitment_policy = MagicMock(__class__=MPL_CommitmentPolicyESDK) + mock_mpl_commitment_policy.return_value = mock_commitment_policy + + # When: _native_to_mpl_get_encryption_materials + output = CryptoMaterialsManagerFromMPL._native_to_mpl_get_encryption_materials( + mock_encryption_materials_request + ) + + # Then: returned MPL_GetEncryptionMaterialsInput is correct + assert isinstance(output, MPL_GetEncryptionMaterialsInput) + assert output.encryption_context == mock_encryption_materials_request.encryption_context + assert output.commitment_policy == mock_commitment_policy + assert output.max_plaintext_length == mock_encryption_materials_request.plaintext_length + + +def test_GIVEN_CommitmentPolicy_FORBID_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_FORBID_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 + # Given: native FORBID_ENCRYPT_ALLOW_DECRYPT + native_commitment_policy = CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + + # When: _native_to_mpl_commmitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + + # Then: Returns MPL FORBID_ENCRYPT_ALLOW_DECRYPT + assert isinstance(output, MPL_CommitmentPolicyESDK) + assert output.value == "FORBID_ENCRYPT_ALLOW_DECRYPT" + + +def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 + # Given: native REQUIRE_ENCRYPT_ALLOW_DECRYPT + native_commitment_policy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT + + # When: _native_to_mpl_commmitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + + # Then: Returns MPL REQUIRE_ENCRYPT_ALLOW_DECRYPT + assert isinstance(output, MPL_CommitmentPolicyESDK) + assert output.value == "REQUIRE_ENCRYPT_ALLOW_DECRYPT" + + +def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_REQUIRE_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_REQUIRE_DECRYPT(): # noqa: E501 + # Given: native REQUIRE_ENCRYPT_REQUIRE_DECRYPT + native_commitment_policy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + + # When: _native_to_mpl_commmitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + + # Then: Returns MPL REQUIRE_ENCRYPT_REQUIRE_DECRYPT + assert isinstance(output, MPL_CommitmentPolicyESDK) + assert output.value == "REQUIRE_ENCRYPT_REQUIRE_DECRYPT" + + +def test_GIVEN_CommitmentPolicy_unrecognized_WHEN_native_to_mpl_commmitment_policy_THEN_raise_ValueError(): + # Given: invalid native commitment policy + native_commitment_policy = "not a commitment policy" + + # Then: Raises ValueError + with pytest.raises(ValueError): + # When: _native_to_mpl_commmitment_policy + CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + + +@patch.object(mock_mpl_cmm, "decrypt_materials") +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._create_mpl_decrypt_materials_input_from_request") +def test_GIVEN_valid_request_WHEN_decrypt_materials_THEN_return_DecryptionMaterialsFromMPL( + mock_native_to_mpl_decrypt_materials, + mock_get_encryption_materials, +): + # Given: mpl_cmm.get_decryption_materials returns mock MPL decryption materials + mock_decrypt_materials_output = MagicMock(__class__=MPL_GetEncryptionMaterialsOutput) + mock_decrypt_materials_output.decryption_materials = mock_mpl_decrypt_materials + mock_get_encryption_materials.return_value = mock_decrypt_materials_output + + # Given: CMMHandler._create_mpl_decrypt_materials_input_from_request creates a MPL_DecryptMaterialsInput + mock_decrypt_materials_input = MagicMock(__class__=MPL_GetEncryptionMaterialsInput) + mock_native_to_mpl_decrypt_materials.return_value = mock_decrypt_materials_input + + # When: decrypt_materials + cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mock_mpl_cmm) + output = cmm.decrypt_materials(mock_decryption_materials_request) + + # Then: + # Verify cmm returns DecryptionMaterialsFromMPL + assert isinstance(output, DecryptionMaterialsFromMPL) + # Verify returned DecryptionMaterialsFromMPL uses the output of `decrypt_materials` + assert output.mpl_materials == mock_mpl_decrypt_materials + # Verify we actually called `decrypt_materials` + mock_mpl_cmm.decrypt_materials.assert_called_once_with(mock_decrypt_materials_input) + + +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._create_mpl_decrypt_materials_input_from_request") +def test_GIVEN_decrypt_materials_raises_MPL_Exception_WHEN_call_decrypt_materials_THEN_raise_ESDK_Exception( + _ +): + # Then: Raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # Given: mpl_cmm.decrypt_materials raises MPL exception + with patch.object(mock_mpl_cmm, "decrypt_materials", + side_effect=AwsCryptographicMaterialProvidersException("any")): + # When: decrypt_materials + cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mock_mpl_cmm) + cmm.decrypt_materials(mock_decryption_materials_request) + + +def test_GIVEN_valid_native_algorithm_id_WHEN_native_algorithm_id_to_mpl_algorithm_id_THEN_returns_valid_MPL_AlgorithmSuiteIdESDK(): # noqa: E501 + # Given: any native algorithm ID + some_native_algorithm_id = 0x1234 # Not a real algorithm ID, but fits the format + + # When: _native_algorithm_id_to_mpl_algorithm_id + mpl_output = CryptoMaterialsManagerFromMPL._native_algorithm_id_to_mpl_algorithm_id( + some_native_algorithm_id + ) + + # Then: returns valid MPL algorithm ID + assert isinstance(mpl_output, MPL_AlgorithmSuiteIdESDK) + assert mpl_output.value == "0x1234" + + +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_algorithm_id_to_mpl_algorithm_id") +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_commmitment_policy") +def test_GIVEN_valid_request_WHEN_create_mpl_decrypt_materials_input_from_request_THEN_returns_MPL_MPL_DecryptMaterialsInput( # noqa: E501 + mock_mpl_commitment_policy, + mock_mpl_algorithm_id, +): + # Given: _native_algorithm_id_to_mpl_algorithm_id returns a valid MPL algorithm ID + mock_algorithm_id = "0x1234" # Some fake algorithm ID that fits the format + mock_mpl_algorithm_id.return_value = mock_algorithm_id + + # Given: _native_to_mpl_commmitment_policy returns some MPL commitment policy + mock_commitment_policy = MagicMock(__class__=MPL_CommitmentPolicyESDK) + mock_mpl_commitment_policy.return_value = mock_commitment_policy + + no_mock_edks = [mock_edk] + one_mock_edk = [mock_edk] + two_mock_edks = [mock_edk, mock_edk] + + # Given: ESK lists of various lengths + for mock_edks in [no_mock_edks, one_mock_edk, two_mock_edks]: + + mock_decryption_materials_request.encrypted_data_keys = mock_edks + + # When: _create_mpl_decrypt_materials_input_from_request + output = CryptoMaterialsManagerFromMPL._create_mpl_decrypt_materials_input_from_request( + mock_decryption_materials_request + ) + + # Then: + # Verify general correctness of output structure + assert isinstance(output, MPL_DecryptMaterialsInput) + assert output.algorithm_suite_id == mock_algorithm_id + assert output.commitment_policy == mock_commitment_policy + assert output.encryption_context == mock_decryption_materials_request.encryption_context + + assert len(output.encrypted_data_keys) == len(mock_edks) + for i in range(len(output.encrypted_data_keys)): + # Assume input[i] == output[i] to make validation easier + # This is how the src is implemented but is not a requirement. + # If this assumption breaks, we should enhance this test. + output_edk = output.encrypted_data_keys[i] + input_edk = mock_edks[i] + assert output_edk.key_provider_id == input_edk.key_provider.provider_id + assert output_edk.key_provider_info == input_edk.key_provider.key_info + assert output_edk.ciphertext == input_edk.encrypted_data_key diff --git a/test/mpl/unit/test_material_managers_mpl_materials.py b/test/mpl/unit/test_material_managers_mpl_materials.py new file mode 100644 index 000000000..9e76556a2 --- /dev/null +++ b/test/mpl/unit/test_material_managers_mpl_materials.py @@ -0,0 +1,189 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Unit test suite to validate aws_encryption_sdk.materials_managers.mpl.materials logic. + +The aws-cryptographic-materials-library MUST be installed to run tests in this module. +""" + +import pytest +from aws_cryptographic_materialproviders.mpl.models import ( + DecryptionMaterials as MPL_DecryptionMaterials, + EncryptedDataKey as MPL_EncryptedDataKey, + EncryptionMaterials as MPL_EncryptionMaterials, +) +from mock import MagicMock, patch +from typing import Dict + +import aws_encryption_sdk.materials_managers.mpl.materials +from aws_encryption_sdk.identifiers import AlgorithmSuite +from aws_encryption_sdk.materials_managers import DecryptionMaterialsRequest, EncryptionMaterialsRequest +from aws_encryption_sdk.materials_managers.mpl.materials import DecryptionMaterialsFromMPL, EncryptionMaterialsFromMPL + +pytestmark = [pytest.mark.unit, pytest.mark.local] + + +mock_mpl_encryption_materials = MagicMock(__class__=MPL_EncryptionMaterials) +mock_mpl_decrypt_materials = MagicMock(__class__=MPL_DecryptionMaterials) + +mock_encryption_materials_request = MagicMock(__class__=EncryptionMaterialsRequest) +mock_encryption_materials_handler = MagicMock(__class__=EncryptionMaterialsFromMPL) +mock_decryption_materials_request = MagicMock(__class__=DecryptionMaterialsRequest) + +mock_edk = MagicMock(__class__=MPL_EncryptedDataKey) +mock_mpl_key_provider_id = MagicMock(__class__=str) +mock_edk.key_provider_id = mock_mpl_key_provider_id +mock_mpl_key_provider_info = MagicMock(__class__=bytes) +mock_edk.key_provider_info = mock_mpl_key_provider_info +mock_mpl_ciphertext = MagicMock(__class__=bytes) +mock_edk.ciphertext = mock_mpl_ciphertext + + +def test_GIVEN_mpl_materials_WHEN_create_EncryptionMaterialsFromMPL_THEN_return_new_CryptoMaterialsManagerFromMPL(): + # Given: valid mpl_materials + # When: create EncryptionMaterialsFromMPL + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + + # Then: EncryptionMaterialsFromMPL is valid + assert mpl_encryption_materials.mpl_materials == mock_mpl_encryption_materials + + +def test_GIVEN_invalid_mpl_materials_WHEN_create_EncryptionMaterialsFromMPL_THEN_raise_ValueError(): + # Then: Raise ValueError + with pytest.raises(ValueError): + # Given: invalid mpl_materials + # When: create EncryptionMaterialsFromMPL + EncryptionMaterialsFromMPL(mpl_materials="not a valid mpl_materials") + + +def test_GIVEN_valid_mpl_algorithm_id_WHEN_mpl_algorithm_id_to_native_algorithm_id_THEN_valid_native_output(): + # Given: any valid MPL algorithm ID + some_mpl_algorithm_id = "0x1234" # Not a real algorithm ID, but fits the format + + # When: _mpl_algorithm_id_to_native_algorithm_id + native_output = aws_encryption_sdk.materials_managers.mpl.materials._mpl_algorithm_id_to_native_algorithm_id( + some_mpl_algorithm_id + ) + + # Then: valid native algorithm ID + assert native_output == 0x1234 + + +@patch("aws_encryption_sdk.materials_managers.mpl.materials._mpl_algorithm_id_to_native_algorithm_id") +@patch("aws_encryption_sdk.materials_managers.mpl.materials.AlgorithmSuite.get_by_id") +def test_GIVEN_valid_mpl_algorithm_id_WHEN_EncryptionMaterials_get_algorithm_THEN_valid_native_algorithm_id( + mock_algorithm, + mock_native_algorithm_id, +): + # Given: _mpl_algorithm_id_to_native_algorithm_id returns a valid native algorithm ID + mock_native_algorithm_id.return_value = 0x1234 + + # Given: get_by_id returns a valid native AlgorithmSuite by looking up an ID + mock_algorithm.return_value = MagicMock(__class__=AlgorithmSuite) + + # When: Get algorithm + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.algorithm + + # Then: output is valid + assert output == mock_algorithm() # property calls automatically, we need to call the mock + + +def test_GIVEN_valid_encryption_context_WHEN_EncryptionMaterials_get_encryption_context_THEN_valid_encryption_context(): + # Given: valid encryption context + mock_encryption_context = MagicMock(__class__=Dict[str, str]) + mock_mpl_encryption_materials.encryption_context = mock_encryption_context + + # When: get encryption context + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.encryption_context + + # Then: returns valid encryption context + assert output == mock_encryption_context + + +def test_GIVEN_valid_edks_WHEN_EncryptionMaterials_get_edks_THEN_returns_edks(): + + # Given: lists of mocked EDKs of various lengths + no_mock_edks = [] + one_mock_edk = [mock_edk] + two_mocked_edks = [mock_edk, mock_edk] + for mock_edks in [no_mock_edks, one_mock_edk, two_mocked_edks]: + mock_mpl_encryption_materials.encrypted_data_keys = mock_edks + + # When: get EDKs + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.encrypted_data_keys + + # Then: returns EDKs + output_as_list = list(output) + # Native ESDK Python types the EDKs as a set; + # Ensure the MPL's list is collapsed into a set correctly + assert len(output_as_list) == len(set(mock_edks)) + for i in range(len(output_as_list)): + # Assume input[i] == output[i] to make validation easier + # This is how the src is implemented but is not a requirement. + # If this assumption breaks, we should enhance this test. + native_edk = output_as_list[i] + mpl_edk = mock_edks[i] + + assert native_edk.encrypted_data_key == mpl_edk.ciphertext + assert native_edk.key_provider.provider_id == mpl_edk.key_provider_id + assert native_edk.key_provider.key_info == mpl_edk.key_provider_info + + +def test_GIVEN_valid_data_key_WHEN_EncryptionMaterials_get_data_key_THEN_returns_data_key(): + # Given: Valid MPL data key + mock_data_key = MagicMock(__class__=bytes) + mock_mpl_encryption_materials.plaintext_data_key = mock_data_key + + # When: get data key + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.data_encryption_key + + # Then: Returns native data key + assert output.key_provider.provider_id == "" + assert output.key_provider.key_info == b"" + assert output.data_key == mock_data_key + assert output.encrypted_data_key == b"" + + +def test_GIVEN_valid_signing_key_WHEN_EncryptionMaterials_get_signing_key_THEN_returns_signing_key(): + # Given: valid signing key + mock_signing_key = MagicMock(__class__=bytes) + mock_mpl_encryption_materials.signing_key = mock_signing_key + + # When: get signing key + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.signing_key + + # Then: returns signing key + assert output == mock_signing_key + + +def test_GIVEN_valid_data_key_WHEN_DecryptionMaterials_get_data_key_THEN_returns_data_key(): + # Given: valid MPL data key + mock_data_key = MagicMock(__class__=bytes) + mock_mpl_decrypt_materials.plaintext_data_key = mock_data_key + + # When: get data key + mpl_decryption_materials = DecryptionMaterialsFromMPL(mpl_materials=mock_mpl_decrypt_materials) + output = mpl_decryption_materials.data_key + + # Then: returns valid native data key + assert output.key_provider.provider_id == "" + assert output.key_provider.key_info == b"" + assert output.data_key == mock_data_key + assert output.encrypted_data_key == b"" + + +def test_GIVEN_valid_verification_key_WHEN_DecryptionMaterials_get_verification_key_THEN_returns_verification_key(): + # Given: valid verification key + mock_verification_key = MagicMock(__class__=bytes) + mock_mpl_decrypt_materials.verification_key = mock_verification_key + + # When: get verification key + mpl_decryption_materials = DecryptionMaterialsFromMPL(mpl_materials=mock_mpl_decrypt_materials) + output = mpl_decryption_materials.verification_key + + # Then: returns verification key + assert output == mock_verification_key diff --git a/test/unit/test_crypto_authentication_signer.py b/test/unit/test_crypto_authentication_signer.py index 11271abfb..425f672ed 100644 --- a/test/unit/test_crypto_authentication_signer.py +++ b/test/unit/test_crypto_authentication_signer.py @@ -11,8 +11,9 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Unit test suite for ``aws_encryption_sdk.internal.crypto.authentication.Signer``.""" +import cryptography.hazmat.primitives.serialization import pytest -from mock import MagicMock, sentinel +from mock import MagicMock, patch, sentinel from pytest_mock import mocker # noqa pylint: disable=unused-import import aws_encryption_sdk.internal.crypto.authentication @@ -77,18 +78,82 @@ def test_f_signer_key_bytes(): assert test.key_bytes() == VALUES["ecc_private_key_prime_private_bytes"] -def test_signer_from_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec): +def test_GIVEN_no_encoding_WHEN_signer_from_key_bytes_THEN_load_der_private_key( + patch_default_backend, + patch_build_hasher, + patch_ec +): mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve) _algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info) - signer = Signer.from_key_bytes(algorithm=_algorithm, key_bytes=sentinel.key_bytes) + # Make a new patched serialization module for this test. + # The default patch introduces serialization as `serialization.Encoding.DER` + # from within the src, but is `Encoding.DER` in the test. + # This namespace change causes the src's `isinstance` checks to fail. + # Mock the `serialization.Encoding.DER` + with patch.object(cryptography.hazmat.primitives, "serialization"): + # Mock the `serialization.load_der_private_key` + with patch.object( + aws_encryption_sdk.internal.crypto.authentication.serialization, + "load_der_private_key" + ) as mock_der: + # When: from_key_bytes + Signer.from_key_bytes( + algorithm=_algorithm, + key_bytes=sentinel.key_bytes, + # Given: No encoding provided => default arg + ) + + # Then: calls load_der_private_key + mock_der.assert_called_once_with( + data=sentinel.key_bytes, password=None, backend=patch_default_backend.return_value + ) + + +def test_GIVEN_PEM_encoding_WHEN_signer_from_key_bytes_THEN_load_pem_private_key( + patch_default_backend, + patch_serialization, + patch_build_hasher, + patch_ec +): + mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve) + _algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info) - patch_serialization.load_der_private_key.assert_called_once_with( + # When: from_key_bytes + signer = Signer.from_key_bytes( + algorithm=_algorithm, + key_bytes=sentinel.key_bytes, + # Given: PEM encoding + encoding=patch_serialization.Encoding.PEM + ) + + # Then: calls load_pem_private_key + patch_serialization.load_pem_private_key.assert_called_once_with( data=sentinel.key_bytes, password=None, backend=patch_default_backend.return_value ) assert isinstance(signer, Signer) assert signer.algorithm is _algorithm - assert signer.key is patch_serialization.load_der_private_key.return_value + assert signer.key is patch_serialization.load_pem_private_key.return_value + + +def test_GIVEN_unrecognized_encoding_WHEN_signer_from_key_bytes_THEN_raise_ValueError( + patch_default_backend, + patch_serialization, + patch_build_hasher, + patch_ec +): + mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve) + _algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info) + + # Then: Raises ValueError + with pytest.raises(ValueError): + # When: from_key_bytes + Signer.from_key_bytes( + algorithm=_algorithm, + key_bytes=sentinel.key_bytes, + # Given: Invalid encoding + encoding="not an encoding" + ) def test_signer_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec): diff --git a/test/unit/test_streaming_client_configs.py b/test/unit/test_streaming_client_configs.py index 426f8f85f..18886f65b 100644 --- a/test/unit/test_streaming_client_configs.py +++ b/test/unit/test_streaming_client_configs.py @@ -15,6 +15,7 @@ import pytest import six +from mock import patch from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.internal.defaults import ALGORITHM, FRAME_LENGTH, LINE_LENGTH @@ -28,6 +29,18 @@ pytestmark = [pytest.mark.unit, pytest.mark.local] +# Check if MPL is installed, and skip tests based on its installation status +# Ideally, this logic would be based on mocking imports and testing logic, +# but doing that introduces errors that cause other tests to fail. +try: + from aws_cryptographic_materialproviders.mpl.references import IKeyring + HAS_MPL = True + + from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL +except ImportError: + HAS_MPL = False + + class FakeCryptoMaterialsManager(CryptoMaterialsManager): def get_encryption_materials(self, request): return @@ -44,6 +57,15 @@ def _new_master_key(self, key_id): return +if HAS_MPL: + class FakeKeyring(IKeyring): + def on_encrypt(self, param): + return + + def on_decrypt(self, param): + return + + BASE_KWARGS = dict( source=b"", materials_manager=FakeCryptoMaterialsManager(), @@ -126,6 +148,18 @@ def test_client_config_defaults(): assert test.max_encrypted_data_keys is None +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +def test_client_config_with_mpl_attr(): + test = _ClientConfig(**BASE_KWARGS) + assert hasattr(test, "keyring") + + +@pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") +def test_client_config_no_mpl(): + test = _ClientConfig(**BASE_KWARGS) + assert not hasattr(test, "keyring") + + def test_encryptor_config_defaults(): test = EncryptorConfig(**BASE_KWARGS) assert test.encryption_context == {} @@ -154,3 +188,93 @@ def test_client_config_converts(kwargs, stream_type): assert isinstance(test.source, stream_type) if test.key_provider is not None: assert isinstance(test.materials_manager, DefaultCryptoMaterialsManager) + + +# Given: no MPL +@pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") +@patch.object(_ClientConfig, "_no_mpl_attrs_post_init") +def test_GIVEN_no_mpl_WHEN_attrs_post_init_THEN_calls_no_mpl_method( + mock_no_mpl_attrs_post_init, +): + # When: attrs_post_init + _ClientConfig(**BASE_KWARGS) + # Then: calls _no_mpl_attrs_post_init + mock_no_mpl_attrs_post_init.assert_called_once_with() + + +# Given: has MPL +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +@patch.object(_ClientConfig, "_has_mpl_attrs_post_init") +def test_GIVEN_has_mpl_WHEN_attrs_post_init_THEN_calls_no_mpl_method( + mock_has_mpl_attrs_post_init, +): + # When: attrs_post_init + _ClientConfig(**BASE_KWARGS) + # Then: calls _has_mpl_attrs_post_init + mock_has_mpl_attrs_post_init.assert_called_once_with() + + +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +@pytest.mark.parametrize( + "kwargs", + ( + (dict(source=b"", materials_manager=FakeCryptoMaterialsManager())), + (dict(source=b"", key_provider=FakeMasterKeyProvider())), + (dict(source="", materials_manager=FakeCryptoMaterialsManager())), + (dict(source=io.BytesIO(), materials_manager=FakeCryptoMaterialsManager())), + (dict(source=six.StringIO(), materials_manager=FakeCryptoMaterialsManager())), + ), +) +def test_client_configs_with_mpl( + kwargs, +): + kwargs["commitment_policy"] = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + + test = _ClientConfig(**kwargs) + + # In all cases, config should have a materials manager + assert test.materials_manager is not None + + # If materials manager was provided, it should be directly used + if hasattr(kwargs, "materials_manager"): + assert kwargs["materials_manager"] == test.materials_manager + + # If MPL keyring was provided, it should be wrapped in MPL materials manager + if hasattr(kwargs, "keyring"): + assert test.keyring is not None + assert test.keyring == kwargs["keyring"] + assert isinstance(test.keyring, IKeyring) + assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) + + # If native key_provider was provided, it should be wrapped in native materials manager + if hasattr(kwargs, "key_provider"): + assert test.key_provider is not None + assert test.key_provider == kwargs["key_provider"] + assert isinstance(test.materials_manager, DefaultCryptoMaterialsManager) + + +# This needs its own test; pytest parametrize cannot use a conditionally-loaded type +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +def test_keyring_client_config_with_mpl( +): + kwargs = { + "source": b"", + "keyring": FakeKeyring(), + "commitment_policy": CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + } + + test = _ClientConfig(**kwargs) + + # In all cases, config should have a materials manager + assert test.materials_manager is not None + + # If materials manager was provided, it should be directly used + if hasattr(kwargs, "materials_manager"): + assert kwargs["materials_manager"] == test.materials_manager + + # If MPL keyring was provided, it should be wrapped in MPL materials manager + if hasattr(kwargs, "keyring"): + assert test.keyring is not None + assert test.keyring == kwargs["keyring"] + assert isinstance(test.keyring, IKeyring) + assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) diff --git a/test/unit/test_streaming_client_mpl_import.py b/test/unit/test_streaming_client_mpl_import.py new file mode 100644 index 000000000..638b04fd6 --- /dev/null +++ b/test/unit/test_streaming_client_mpl_import.py @@ -0,0 +1,37 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Unit test suite to validate aws_encryption_sdk.streaming_client MPL import logic.""" + +import pytest + +import aws_encryption_sdk.streaming_client + +pytestmark = [pytest.mark.unit, pytest.mark.local] + + +# Check if MPL is installed, and skip tests based on its installation status +# Ideally, this logic would be based on mocking imports and testing logic, +# but doing that introduces errors that cause other tests to fail. +try: + import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import + HAS_MPL = True +except ImportError: + HAS_MPL = False + + +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +def test_GIVEN_test_has_mpl_is_True_THEN_streaming_client_has_mpl_is_True(): + """If the MPL IS installed in the runtime environment, + assert the streaming client has _HAS_MPL set to True""" + + assert hasattr(aws_encryption_sdk.streaming_client, "_HAS_MPL") + assert aws_encryption_sdk.streaming_client._HAS_MPL is True + + +@pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") +def test_GIVEN_test_has_mpl_is_False_THEN_streaming_client_has_mpl_is_False(): + """If the MPL IS NOT installed in the runtime environment, + assert the streaming client has _HAS_MPL set to False""" + + assert hasattr(aws_encryption_sdk.streaming_client, "_HAS_MPL") + assert aws_encryption_sdk.streaming_client._HAS_MPL is False diff --git a/test/unit/test_streaming_client_stream_decryptor.py b/test/unit/test_streaming_client_stream_decryptor.py index 157755094..e06cad308 100644 --- a/test/unit/test_streaming_client_stream_decryptor.py +++ b/test/unit/test_streaming_client_stream_decryptor.py @@ -33,14 +33,31 @@ pytestmark = [pytest.mark.unit, pytest.mark.local] +# Check if MPL is installed, and skip tests based on its installation status +# Ideally, this logic would be based on mocking imports and testing logic, +# but doing that introduces errors that cause other tests to fail. +try: + from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL + HAS_MPL = True + +except ImportError: + HAS_MPL = False + + class TestStreamDecryptor(object): @pytest.fixture(autouse=True) def apply_fixtures(self): self.mock_key_provider = MagicMock(__class__=MasterKeyProvider) self.mock_materials_manager = MagicMock(__class__=CryptoMaterialsManager) - self.mock_materials_manager.decrypt_materials.return_value = MagicMock( + self.mock_decrypt_materials = MagicMock( data_key=VALUES["data_key_obj"], verification_key=sentinel.verification_key ) + self.mock_materials_manager.decrypt_materials.return_value = self.mock_decrypt_materials + + if HAS_MPL: + self.mock_mpl_materials_manager = MagicMock(__class__=CryptoMaterialsManagerFromMPL) + self.mock_mpl_materials_manager.decrypt_materials.return_value = self.mock_decrypt_materials + self.mock_header = MagicMock() self.mock_header.version = SerializationVersion.V1 self.mock_header.algorithm = MagicMock( @@ -213,6 +230,103 @@ def test_read_header(self, mock_derive_datakey, mock_decrypt_materials_request, assert test_header is self.mock_header assert test_header_auth is sentinel.header_auth + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.Verifier") + # Given: no MPL + @pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") + def test_GIVEN_verification_key_AND_no_mpl_WHEN_read_header_THEN_calls_from_key_bytes( + self, + mock_verifier, + *_, + ): + # Given: verification key + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + ct_stream = io.BytesIO(VALUES["data_128"]) + mock_commitment_policy = MagicMock(__class__=CommitmentPolicy) + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=ct_stream, + commitment_policy=mock_commitment_policy, + ) + test_decryptor.source_stream = ct_stream + test_decryptor._stream_length = len(VALUES["data_128"]) + + # When: read header + test_decryptor._read_header() + + # Then: calls from_key_bytes + mock_verifier.from_key_bytes.assert_called_once_with( + algorithm=self.mock_header.algorithm, key_bytes=sentinel.verification_key + ) + + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.Verifier") + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_verification_key_AND_has_mpl_AND_not_MPLCMM_WHEN_read_header_THEN_calls_from_key_bytes( + self, + mock_verifier, + *_, + ): + # Given: verification key + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + ct_stream = io.BytesIO(VALUES["data_128"]) + mock_commitment_policy = MagicMock(__class__=CommitmentPolicy) + test_decryptor = StreamDecryptor( + # Given: native CMM + materials_manager=self.mock_materials_manager, + source=ct_stream, + commitment_policy=mock_commitment_policy, + ) + test_decryptor.source_stream = ct_stream + test_decryptor._stream_length = len(VALUES["data_128"]) + + # When: read_header + test_decryptor._read_header() + + # Then: calls from_key_bytess + mock_verifier.from_key_bytes.assert_called_once_with( + algorithm=self.mock_header.algorithm, key_bytes=sentinel.verification_key + ) + + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.Verifier") + @patch("base64.b64encode") + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_verification_key_AND_has_mpl_AND_has_MPLCMM_WHEN_read_header_THEN_calls_from_encoded_point( + self, + mock_b64encoding, + mock_verifier, + *_, + ): + # Given: Verification key + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + ct_stream = io.BytesIO(VALUES["data_128"]) + mock_commitment_policy = MagicMock(__class__=CommitmentPolicy) + test_decryptor = StreamDecryptor( + # Given: MPL CMM + materials_manager=self.mock_mpl_materials_manager, + source=ct_stream, + commitment_policy=mock_commitment_policy, + ) + test_decryptor.source_stream = ct_stream + test_decryptor._stream_length = len(VALUES["data_128"]) + + # When: read header + test_decryptor._read_header() + + # Then: calls from_encoded_point + mock_verifier.from_encoded_point.assert_called_once_with( + algorithm=self.mock_header.algorithm, encoded_point=mock_b64encoding() + ) + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") def test_read_header_frame_too_large(self, mock_derive_datakey): self.mock_header.content_type = ContentType.FRAMED_DATA diff --git a/test/unit/test_streaming_client_stream_encryptor.py b/test/unit/test_streaming_client_stream_encryptor.py index 5bfd0c903..e43752689 100644 --- a/test/unit/test_streaming_client_stream_encryptor.py +++ b/test/unit/test_streaming_client_stream_encryptor.py @@ -15,6 +15,7 @@ import pytest import six +from cryptography.hazmat.primitives import serialization from mock import MagicMock, call, patch, sentinel import aws_encryption_sdk.internal.defaults @@ -37,6 +38,17 @@ pytestmark = [pytest.mark.unit, pytest.mark.local] +# Check if MPL is installed, and skip tests based on its installation status +# Ideally, this logic would be based on mocking imports and testing logic, +# but doing that introduces errors that cause other tests to fail. +try: + from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL + HAS_MPL = True + +except ImportError: + HAS_MPL = False + + class TestStreamEncryptor(object): @pytest.fixture(autouse=True) def apply_fixtures(self): @@ -60,6 +72,10 @@ def apply_fixtures(self): self.mock_master_keys_set, ) + if HAS_MPL: + self.mock_mpl_materials_manager = MagicMock(__class__=CryptoMaterialsManagerFromMPL) + self.mock_mpl_materials_manager.get_encryption_materials.return_value = self.mock_encryption_materials + self.mock_master_key = MagicMock(__class__=MasterKey) self.mock_frame_length = MagicMock(__class__=int) @@ -366,6 +382,75 @@ def test_prep_message_non_framed_message(self, mock_write_header, mock_prep_non_ test_encryptor._prep_message() mock_prep_non_framed.assert_called_once_with() + # Given: no MPL + @pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") + def test_GIVEN_no_mpl_AND_uses_signer_WHEN_prep_message_THEN_signer_uses_default_encoding(self): + self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 + test_encryptor = StreamEncryptor( + source=VALUES["data_128"], + materials_manager=self.mock_materials_manager, + frame_length=self.mock_frame_length, + algorithm=Algorithm.AES_128_GCM_IV12_TAG16, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.content_type = ContentType.FRAMED_DATA + with patch.object(self.mock_signer, "from_key_bytes"): + # When: prep message + test_encryptor._prep_message() + # Then: calls from_key_bytes with default encoding + self.mock_signer.from_key_bytes.assert_called_once_with( + algorithm=self.mock_encryption_materials.algorithm, + key_bytes=self.mock_encryption_materials.signing_key + ) + + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_mpl_AND_not_MPLCMM_AND_uses_signer_WHEN_prep_message_THEN_signer_uses_default_encoding(self): + self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 + test_encryptor = StreamEncryptor( + source=VALUES["data_128"], + # Given: native CMM + materials_manager=self.mock_materials_manager, + frame_length=self.mock_frame_length, + algorithm=Algorithm.AES_128_GCM_IV12_TAG16, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.content_type = ContentType.FRAMED_DATA + with patch.object(self.mock_signer, "from_key_bytes"): + # When: prep_message + test_encryptor._prep_message() + # Then: calls from_key_bytes with default encoding + self.mock_signer.from_key_bytes.assert_called_once_with( + algorithm=self.mock_encryption_materials.algorithm, + key_bytes=self.mock_encryption_materials.signing_key + ) + + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_mpl_AND_has_MPLCMM_AND_uses_signer_WHEN_prep_message_THEN_signer_uses_PEM_encoding(self): + self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 + test_encryptor = StreamEncryptor( + source=VALUES["data_128"], + # Given: MPL CMM + materials_manager=self.mock_mpl_materials_manager, + frame_length=self.mock_frame_length, + algorithm=Algorithm.AES_128_GCM_IV12_TAG16, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.content_type = ContentType.FRAMED_DATA + with patch.object(self.mock_signer, "from_key_bytes"): + # When: prep_message + test_encryptor._prep_message() + self.mock_signer.from_key_bytes.assert_called_once_with( + algorithm=self.mock_encryption_materials.algorithm, + key_bytes=self.mock_encryption_materials.signing_key, + # Then: calls from_key_bytes with PEM encoding + encoding=serialization.Encoding.PEM + ) + def test_prep_message_no_signer(self): self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 test_encryptor = StreamEncryptor( diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index c6d565108..69f9f060d 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -265,3 +265,28 @@ def test_source_data_key_length_check_invalid(self): source_data_key=mock_data_key, algorithm=mock_algorithm ) excinfo.match("Invalid Source Data Key length 4 for algorithm required: 5") + + def test_exactly_one_arg_is_not_none(self): + # No args => no args are not None + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none() is False + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + None + ) is False + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + "not None" + ) is True + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + "not None", "also not None" + ) is False + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + "not None", None + ) is True + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + "not None", "also not None" + ) is False + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + None, "not None" + ) is True + assert aws_encryption_sdk.internal.utils.exactly_one_arg_is_not_none( + None, None + ) is False diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index 643750cd2..580b641e0 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -2,7 +2,8 @@ envlist = # The test vectors depend on new features now, # so until release we can only effectively test the local version of the ESDK. - py{37,38,39,310}-awses_local, + py{37,38,39,310}-awses_local + py{311,312}-awses_local{,-mpl} # 1.2.0 and 1.2.max are being difficult because of attrs bandit, doc8, readme, {flake8,pylint}{,-tests}, @@ -48,6 +49,8 @@ passenv = sitepackages = False deps = -rtest/requirements.txt + # Install the MPL requirements if the `-mpl` suffix is present + mpl: -r../requirements_mpl.txt .. commands = {[testenv:base-command]commands} diff --git a/tox.ini b/tox.ini index aa1ea5325..6a4c3d10c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,24 @@ [tox] envlist = - py{37,38,39,310,311,312}-{local,integ,accept,examples}, nocmk, + # <3.11: run all non-MPL tests + py{37,38,39,310}-{local,integ,accept,examples}, + # >=3.11: run all tests with MPL installed and without MPL installed + # The `-mpl` suffix tells tox to install the MPL. + # In the case where the suffix IS NOT appended, + # this runs tests for the target version WITHOUT the MPL installed. + # In the case where the suffix IS appended, + # this runs tests for the target version WITH the MPL installed. + # This does not run any MPL-specific tests; it only runs non-MPL-specific + # tests in a test environment that also has the MPL. + py{311,312}-{local,integ,accept,examples}{,-mpl}, + # >=3.11: Run ONLY the MPL-specific tests. + # These must be separate from the above target, since + # these require the `-mpl` suffix. + # The `mpl` prefix specifies a separate target, + # i.e. `mpllocal` instead of `local`. + # `mplXXX` contains tests using MPL components. + py{311,312}-mpl{local,examples}-mpl + nocmk, bandit, doc8, readme, docs, {flake8,pylint}{,-tests,-examples}, isort-check, black-check, @@ -61,18 +79,28 @@ passenv = # Pass through custom pip config file settings PIP_CONFIG_FILE sitepackages = False -deps = -rdev_requirements/test-requirements.txt +deps = + -rdev_requirements/test-requirements.txt + # Install the MPL requirements if the `-mpl` suffix is present + mpl: -rrequirements_mpl.txt commands = - local: {[testenv:base-command]commands} test/ -m local - integ: {[testenv:base-command]commands} test/ -m integ - accept: {[testenv:base-command]commands} test/ -m accept - examples: {[testenv:base-command]commands} examples/test/ -m examples - all: {[testenv:base-command]commands} test/ examples/test/ + local: {[testenv:base-command]commands} test/ -m local --ignore test/mpl/ + # MPL unit tests require the MPL to be installed + mpllocal: {[testenv:base-command]commands} test/ -m local + integ: {[testenv:base-command]commands} test/ -m integ --ignore test/mpl/ + accept: {[testenv:base-command]commands} test/ -m accept --ignore test/mpl/ + examples: {[testenv:base-command]commands} examples/test/ -m examples --ignore examples/test/keyrings/ + # MPL keyring examples require a special IAM role; run these separately under a separate set of permissions + mplexamples: {[testenv:base-command]commands} examples/test/keyrings -m examples + all: {[testenv:base-command]commands} test/ examples/test/ --ignore test/mpl/ --ignore examples/test/keyrings/ + mplall: {[testenv:base-command]commands} test/ examples/test/ manual: {[testenv:base-command]commands} # Run code coverage on the unit tests [testenv:coverage] -commands = {[testenv:base-command]commands} --cov aws_encryption_sdk test/ -m local +commands = {[testenv:base-command]commands} --cov aws_encryption_sdk test/ -m local --ignore test/mpl/ +[testenv:mplcoverage-mpl] +commands = {[testenv:base-command]commands} --cov-config=.coveragercmpl --cov aws_encryption_sdk test/ -m local # Verify that local tests work without environment variables present [testenv:nocmk] @@ -84,7 +112,7 @@ passenv = setenv = ######################################################### deps = -rdev_requirements/test-requirements.txt -commands = {[testenv:base-command]commands} test/ -m local +commands = {[testenv:base-command]commands} test/ -m local --ignore test/mpl/ # Collect requirements for use in upstream tests [testenv:freeze-upstream-requirements-base] @@ -107,7 +135,7 @@ commands = {[testenv:freeze-upstream-requirements-base]commands} test/upstream-r [testenv:test-upstream-requirements-base] sitepackages = False recreate = True -commands = {[testenv:base-command]commands} test/ -m local +commands = {[testenv:base-command]commands} test/ -m local --ignore test/mpl/ # Test frozen upstream requirements for Python 3.11 [testenv:test-upstream-requirements-py311] @@ -158,13 +186,14 @@ commands = --max-module-lines=1500 \ src/aws_encryption_sdk/ \ setup.py + --ignore-paths=src/aws_encryption_sdk/internal/mpl/ [testenv:pylint-examples] basepython = {[testenv:pylint]basepython} deps = {[testenv:pylint]deps} commands = - pylint --rcfile=examples/src/pylintrc examples/src/ - pylint --rcfile=examples/test/pylintrc --disable R0801 examples/test/ + pylint --rcfile=examples/src/pylintrc examples/src/ --ignore-paths=examples/src/keyrings + pylint --rcfile=examples/test/pylintrc --disable R0801 examples/test/ --ignore-paths=examples/test/keyrings [testenv:pylint-tests] basepython = {[testenv:pylint]basepython} From 44d91925f51f71067f4fb0eb9eafd7cec426b376 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 26 Apr 2024 10:46:58 -0700 Subject: [PATCH 02/51] feat: Required encryption context CMM (#645) --- examples/src/keyrings/hierarchical_keyring.py | 33 ++- .../required_encryption_context_cmm.py | 158 +++++++++++ .../keyrings/test_i_hierarchical_keyring.py | 2 +- .../test_i_required_encryption_context_cmm.py | 13 + setup.py | 2 +- src/aws_encryption_sdk/__init__.py | 3 + .../internal/formatting/serialize.py | 104 +++++-- .../materials_managers/__init__.py | 6 + .../materials_managers/mpl/cmm.py | 1 + .../materials_managers/mpl/materials.py | 19 ++ src/aws_encryption_sdk/streaming_client.py | 196 ++++++++++++-- .../unit/test_material_managers_mpl_cmm.py | 3 + .../test_material_managers_mpl_materials.py | 39 +++ test/unit/test_serialize.py | 56 ++++ test/unit/test_streaming_client_configs.py | 58 ++-- .../test_streaming_client_stream_decryptor.py | 254 ++++++++++++++++++ .../test_streaming_client_stream_encryptor.py | 161 +++++++++++ .../aws-crypto-tools-test-vector-framework | 2 +- 18 files changed, 1045 insertions(+), 65 deletions(-) create mode 100644 examples/src/keyrings/required_encryption_context_cmm.py create mode 100644 examples/test/keyrings/test_i_required_encryption_context_cmm.py diff --git a/examples/src/keyrings/hierarchical_keyring.py b/examples/src/keyrings/hierarchical_keyring.py index aa87485f9..32a6cbf8b 100644 --- a/examples/src/keyrings/hierarchical_keyring.py +++ b/examples/src/keyrings/hierarchical_keyring.py @@ -1,6 +1,36 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""Example showing basic encryption and decryption of a value already in memory.""" +""" +This example sets up the Hierarchical Keyring, which establishes a key hierarchy where "branch" +keys are persisted in DynamoDb. These branch keys are used to protect your data keys, and these +branch keys are themselves protected by a KMS Key. + +Establishing a key hierarchy like this has two benefits: +First, by caching the branch key material, and only calling KMS to re-establish authentication +regularly according to your configured TTL, you limit how often you need to call KMS to protect +your data. This is a performance security tradeoff, where your authentication, audit, and logging +from KMS is no longer one-to-one with every encrypt or decrypt call. Additionally, KMS Cloudtrail +cannot be used to distinguish Encrypt and Decrypt calls, and you cannot restrict who has +Encryption rights from who has Decryption rights since they both ONLY need KMS:Decrypt. However, +the benefit is that you no longer have to make a network call to KMS for every encrypt or +decrypt. + +Second, this key hierarchy facilitates cryptographic isolation of a tenant's data in a +multi-tenant data store. Each tenant can have a unique Branch Key, that is only used to protect +the tenant's data. You can either statically configure a single branch key to ensure you are +restricting access to a single tenant, or you can implement an interface that selects the Branch +Key based on the Encryption Context. + +This example demonstrates configuring a Hierarchical Keyring with a Branch Key ID Supplier to +encrypt and decrypt data for two separate tenants. + +This example requires access to the DDB Table where you are storing the Branch Keys. This +table must be configured with the following primary key configuration: - Partition key is named +"partition_key" with type (S) - Sort key is named "sort_key" with type (S). + +This example also requires using a KMS Key. You need the following access on this key: - +GenerateDataKeyWithoutPlaintext - Decrypt +""" import sys import boto3 @@ -25,6 +55,7 @@ from .example_branch_key_id_supplier import ExampleBranchKeyIdSupplier +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. module_root_dir = '/'.join(__file__.split("/")[:-1]) sys.path.append(module_root_dir) diff --git a/examples/src/keyrings/required_encryption_context_cmm.py b/examples/src/keyrings/required_encryption_context_cmm.py new file mode 100644 index 000000000..e0c19697c --- /dev/null +++ b/examples/src/keyrings/required_encryption_context_cmm.py @@ -0,0 +1,158 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Demonstrate an encrypt/decrypt cycle using a Required Encryption Context CMM. +A required encryption context CMM asks for required keys in the encryption context field +on encrypt such that they will not be stored on the message, but WILL be included in the header signature. +On decrypt, the client MUST supply the key/value pair(s) that were not stored to successfully decrypt the message. +""" +import sys + +import boto3 +# Ignore missing MPL for pylint, but the MPL is required for this example +# noqa pylint: disable=import-error +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsKeyringInput, + CreateDefaultCryptographicMaterialsManagerInput, + CreateRequiredEncryptionContextCMMInput, +) +from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from typing import Dict, List + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks +module_root_dir = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(module_root_dir) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str +): + """Creates a hierarchical keyring using the provided resources, then encrypts and decrypts a string with it.""" + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create an encryption context. + # Most encrypted data should have an associated encryption context + # to protect integrity. This sample uses placeholder values. + # For more information see: + # blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management # noqa: E501 + encryption_context: Dict[str, str] = { + "key1": "value1", + "key2": "value2", + "requiredKey1": "requiredValue1", + "requiredKey2": "requiredValue2", + } + + # 3. Create list of required encryption context keys. + # This is a list of keys that must be present in the encryption context. + required_encryption_context_keys: List[str] = ["requiredKey1", "requiredKey2"] + + # 4. Create the AWS KMS keyring. + mpl: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=boto3.client('kms', region_name="us-west-2") + ) + kms_keyring: IKeyring = mpl.create_aws_kms_keyring(keyring_input) + + # 5. Create the required encryption context CMM. + underlying_cmm: ICryptographicMaterialsManager = \ + mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=kms_keyring + ) + ) + + required_ec_cmm: ICryptographicMaterialsManager = \ + mpl.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + required_encryption_context_keys=required_encryption_context_keys, + underlying_cmm=underlying_cmm, + ) + ) + + # 6. Encrypt the data + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + materials_manager=required_ec_cmm, + encryption_context=encryption_context + ) + + # 7. Reproduce the encryption context. + # The reproduced encryption context MUST contain a value for + # every key in the configured required encryption context keys during encryption with + # Required Encryption Context CMM. + reproduced_encryption_context: Dict[str, str] = { + "requiredKey1": "requiredValue1", + "requiredKey2": "requiredValue2", + } + + # 8. Decrypt the data + plaintext_bytes_A, _ = client.decrypt( + source=ciphertext, + materials_manager=required_ec_cmm, + encryption_context=reproduced_encryption_context + ) + assert plaintext_bytes_A == EXAMPLE_DATA + + # We can also decrypt using the underlying CMM, + # but must also provide the reproduced encryption context + plaintext_bytes_A, _ = client.decrypt( + source=ciphertext, + materials_manager=underlying_cmm, + encryption_context=reproduced_encryption_context + ) + assert plaintext_bytes_A == EXAMPLE_DATA + + # 9. Extra: Demonstrate that if we don't provide the reproduced encryption context, + # decryption will fail. + try: + plaintext_bytes_A, _ = client.decrypt( + source=ciphertext, + materials_manager=required_ec_cmm, + # No reproduced encryption context for required EC CMM-produced message makes decryption fail. + ) + raise Exception("If this exception is raised, decryption somehow succeeded!") + except AWSEncryptionSDKClientError: + # Swallow specific expected exception. + # We expect decryption to fail with an AWSEncryptionSDKClientError + # since we did not provide reproduced encryption context when decrypting + # a message encrypted with the requried encryption context CMM. + pass + + # Same for the default CMM; + # If we don't provide the reproduced encryption context, decryption will fail. + try: + plaintext_bytes_A, _ = client.decrypt( + source=ciphertext, + materials_manager=required_ec_cmm, + # No reproduced encryption context for required EC CMM-produced message makes decryption fail. + ) + raise Exception("If this exception is raised, decryption somehow succeeded!") + except AWSEncryptionSDKClientError: + # Swallow specific expected exception. + # We expect decryption to fail with an AWSEncryptionSDKClientError + # since we did not provide reproduced encryption context when decrypting + # a message encrypted with the requried encryption context CMM, + # even though we are using a default CMM on decrypt. + pass diff --git a/examples/test/keyrings/test_i_hierarchical_keyring.py b/examples/test/keyrings/test_i_hierarchical_keyring.py index 4cae478d7..c4583534a 100644 --- a/examples/test/keyrings/test_i_hierarchical_keyring.py +++ b/examples/test/keyrings/test_i_hierarchical_keyring.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""Unit test suite for the hierarchical keyring example.""" +"""Test suite for the hierarchical keyring example.""" import pytest from ...src.keyrings.hierarchical_keyring import encrypt_and_decrypt_with_keyring diff --git a/examples/test/keyrings/test_i_required_encryption_context_cmm.py b/examples/test/keyrings/test_i_required_encryption_context_cmm.py new file mode 100644 index 000000000..724705faa --- /dev/null +++ b/examples/test/keyrings/test_i_required_encryption_context_cmm.py @@ -0,0 +1,13 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the required encryption context CMM example.""" +import pytest + +from ...src.keyrings.required_encryption_context_cmm import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + key_arn = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_keyring(key_arn) diff --git a/setup.py b/setup.py index 0615a43c7..697cb96ce 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ def get_requirements(): license="Apache License 2.0", install_requires=get_requirements(), # pylint: disable=fixme - # TODO: Point at PyPI once MPL is released. + # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ "MPL": ["aws-cryptographic-material-providers @" \ diff --git a/src/aws_encryption_sdk/__init__.py b/src/aws_encryption_sdk/__init__.py index 661d41ee6..74732bfc5 100644 --- a/src/aws_encryption_sdk/__init__.py +++ b/src/aws_encryption_sdk/__init__.py @@ -185,6 +185,9 @@ def decrypt(self, **kwargs): If source_length is not provided and read() is called, will attempt to seek() to the end of the stream and tell() to find the length of source data. + :param dict encryption_context: Dictionary defining encryption context to validate + on decrypt. This is ONLY validated on decrypt if using a CMM from the + aws-cryptographic-material-providers library. :param int max_body_length: Maximum frame size (or content length for non-framed messages) in bytes to read from ciphertext message. :returns: Tuple containing the decrypted plaintext and the message header object diff --git a/src/aws_encryption_sdk/internal/formatting/serialize.py b/src/aws_encryption_sdk/internal/formatting/serialize.py index b4d866099..9f1325f98 100644 --- a/src/aws_encryption_sdk/internal/formatting/serialize.py +++ b/src/aws_encryption_sdk/internal/formatting/serialize.py @@ -189,7 +189,13 @@ def serialize_header(header, signer=None): raise SerializationError("Unrecognized message format version: {}".format(header.version)) -def _serialize_header_auth_v1(algorithm, header, data_encryption_key, signer=None): +def _serialize_header_auth_v1( + algorithm, + header, + data_encryption_key, + signer=None, + required_ec_bytes=None +): """Creates serialized header authentication data for messages in serialization version V1. :param algorithm: Algorithm to use for encryption @@ -198,16 +204,35 @@ def _serialize_header_auth_v1(algorithm, header, data_encryption_key, signer=Non :param bytes data_encryption_key: Data key with which to encrypt message :param signer: Cryptographic signer object (optional) :type signer: aws_encryption_sdk.Signer + :param required_encryption_context_bytes: Serialized encryption context items + for all items whose keys are in the required_encryption_context list. + This is ONLY processed if using the aws-cryptographic-materialproviders library + AND its required encryption context CMM. (optional) + :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data :rtype: bytes """ - header_auth = encrypt( - algorithm=algorithm, - key=data_encryption_key, - plaintext=b"", - associated_data=header, - iv=header_auth_iv(algorithm), - ) + if required_ec_bytes is None: + header_auth = encrypt( + algorithm=algorithm, + key=data_encryption_key, + plaintext=b"", + associated_data=header, + iv=header_auth_iv(algorithm), + ) + else: + header_auth = encrypt( + algorithm=algorithm, + key=data_encryption_key, + plaintext=b"", + # The AAD MUST be the concatenation of the serialized message header body and the serialization + # of encryption context to only authenticate. The encryption context to only authenticate MUST + # be the encryption context in the encryption materials filtered to only contain key value + # pairs listed in the encryption material's required encryption context keys serialized + # according to the encryption context serialization specification. + associated_data=header + required_ec_bytes, + iv=header_auth_iv(algorithm), + ) output = struct.pack( ">{iv_len}s{tag_len}s".format(iv_len=algorithm.iv_len, tag_len=algorithm.tag_len), header_auth.iv, @@ -218,7 +243,13 @@ def _serialize_header_auth_v1(algorithm, header, data_encryption_key, signer=Non return output -def _serialize_header_auth_v2(algorithm, header, data_encryption_key, signer=None): +def _serialize_header_auth_v2( + algorithm, + header, + data_encryption_key, + signer=None, + required_ec_bytes=None +): """Creates serialized header authentication data for messages in serialization version V2. :param algorithm: Algorithm to use for encryption @@ -227,16 +258,35 @@ def _serialize_header_auth_v2(algorithm, header, data_encryption_key, signer=Non :param bytes data_encryption_key: Data key with which to encrypt message :param signer: Cryptographic signer object (optional) :type signer: aws_encryption_sdk.Signer + :param required_encryption_context_bytes: Serialized encryption context items + for all items whose keys are in the required_encryption_context list. + This is ONLY processed if using the aws-cryptographic-materialproviders library + AND its required encryption context CMM. (optional) + :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data :rtype: bytes """ - header_auth = encrypt( - algorithm=algorithm, - key=data_encryption_key, - plaintext=b"", - associated_data=header, - iv=header_auth_iv(algorithm), - ) + if required_ec_bytes is None: + header_auth = encrypt( + algorithm=algorithm, + key=data_encryption_key, + plaintext=b"", + associated_data=header, + iv=header_auth_iv(algorithm), + ) + else: + header_auth = encrypt( + algorithm=algorithm, + key=data_encryption_key, + plaintext=b"", + # The AAD MUST be the concatenation of the serialized message header body and the serialization + # of encryption context to only authenticate. The encryption context to only authenticate MUST + # be the encryption context in the encryption materials filtered to only contain key value + # pairs listed in the encryption material's required encryption context keys serialized + # according to the encryption context serialization specification. + associated_data=header + required_ec_bytes, + iv=header_auth_iv(algorithm), + ) output = struct.pack( ">{tag_len}s".format(tag_len=algorithm.tag_len), header_auth.tag, @@ -246,7 +296,14 @@ def _serialize_header_auth_v2(algorithm, header, data_encryption_key, signer=Non return output -def serialize_header_auth(version, algorithm, header, data_encryption_key, signer=None): +def serialize_header_auth( + version, + algorithm, + header, + data_encryption_key, + signer=None, + required_ec_bytes=None +): """Creates serialized header authentication data. :param version: The serialization version of the message @@ -257,13 +314,22 @@ def serialize_header_auth(version, algorithm, header, data_encryption_key, signe :param bytes data_encryption_key: Data key with which to encrypt message :param signer: Cryptographic signer object (optional) :type signer: aws_encryption_sdk.Signer + :param required_encryption_context_bytes: Serialized encryption context items + for all items whose keys are in the required_encryption_context list. + This is ONLY processed if using the aws-cryptographic-materialproviders library + AND its required encryption context CMM. (optional) + :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data :rtype: bytes """ if version == SerializationVersion.V1: - return _serialize_header_auth_v1(algorithm, header, data_encryption_key, signer) + return _serialize_header_auth_v1( + algorithm, header, data_encryption_key, signer, required_ec_bytes + ) elif version == SerializationVersion.V2: - return _serialize_header_auth_v2(algorithm, header, data_encryption_key, signer) + return _serialize_header_auth_v2( + algorithm, header, data_encryption_key, signer, required_ec_bytes + ) else: raise SerializationError("Unrecognized message format version: {}".format(version)) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 9db1dafae..950dd87cd 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -89,11 +89,17 @@ class DecryptionMaterialsRequest(object): :param encrypted_data_keys: Set of encrypted data keys :type encrypted_data_keys: set of `aws_encryption_sdk.structures.EncryptedDataKey` :param dict encryption_context: Encryption context to provide to master keys for underlying decrypt requests + :param dict reproduced_encryption_context: Encryption context to provide on decrypt. + This is ONLY processed if using a CMM from the aws-cryptographic-materialproviders library. """ algorithm = attr.ib(validator=attr.validators.instance_of(Algorithm)) encrypted_data_keys = attr.ib(validator=attr.validators.instance_of(set)) encryption_context = attr.ib(validator=attr.validators.instance_of(dict)) + reproduced_encryption_context = attr.ib( + default=None, + validator=attr.validators.optional(attr.validators.instance_of(dict)) + ) commitment_policy = attr.ib( default=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT, validator=attr.validators.optional(attr.validators.instance_of(CommitmentPolicy)), diff --git a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py index 880e37203..1f2102757 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py @@ -143,5 +143,6 @@ def _create_mpl_decrypt_materials_input_from_request( ), encrypted_data_keys=list_edks, encryption_context=request.encryption_context, + reproduced_encryption_context=request.reproduced_encryption_context, ) return output diff --git a/src/aws_encryption_sdk/materials_managers/mpl/materials.py b/src/aws_encryption_sdk/materials_managers/mpl/materials.py index dfd1bd6fc..54ea21b39 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/materials.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/materials.py @@ -96,6 +96,13 @@ def signing_key(self) -> bytes: """Materials' signing key.""" return self.mpl_materials.signing_key + @property + # Pylint thinks this name is too long, but it's the best descriptor for this... + # pylint: disable=invalid-name + def required_encryption_context_keys(self) -> bytes: + """Materials' required encryption context keys.""" + return self.mpl_materials.required_encryption_context_keys + class DecryptionMaterialsFromMPL(Native_DecryptionMaterials): """ @@ -136,3 +143,15 @@ def data_key(self) -> DataKey: def verification_key(self) -> bytes: """Materials' verification key.""" return self.mpl_materials.verification_key + + @property + def encryption_context(self) -> Dict[str, str]: + """Materials' encryption context.""" + return self.mpl_materials.encryption_context + + @property + # Pylint thinks this name is too long, but it's the best descriptor for this... + # pylint: disable=invalid-name + def required_encryption_context_keys(self) -> bytes: + """Materials' required encryption context keys.""" + return self.mpl_materials.required_encryption_context_keys diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 5bf953244..a86112610 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -77,7 +77,10 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException from aws_cryptographic_materialproviders.mpl.models import CreateDefaultCryptographicMaterialsManagerInput - from aws_cryptographic_materialproviders.mpl.references import IKeyring + from aws_cryptographic_materialproviders.mpl.references import ( + ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, + IKeyring as MPL_IKeyring, + ) _HAS_MPL = True # Import internal ESDK modules that depend on the MPL @@ -126,16 +129,37 @@ class _ClientConfig(object): # pylint: disable=too-many-instance-attributes max_encrypted_data_keys = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(int)) ) - materials_manager = attr.ib( - hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(CryptoMaterialsManager)) - ) + if _HAS_MPL: + # With the MPL, the provided materials_manager can be an instance of + # either the native interface or an MPL interface. + # If it implements the MPL interface, this constructor will + # internally wrap it in a native interface. + materials_manager = attr.ib( + hash=True, + default=None, + validator=attr.validators.optional( + attr.validators.instance_of( + (CryptoMaterialsManager, MPL_ICryptographicMaterialsManager) + ) + ) + ) + else: + materials_manager = attr.ib( + hash=True, + default=None, + validator=attr.validators.optional( + attr.validators.instance_of( + CryptoMaterialsManager + ) + ) + ) key_provider = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(MasterKeyProvider)) ) if _HAS_MPL: # Keyrings are only available if the MPL is installed in the runtime keyring = attr.ib( - hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(IKeyring)) + hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(MPL_IKeyring)) ) source_length = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)) @@ -173,6 +197,12 @@ def _has_mpl_attrs_post_init(self): # so customers only have to catch ESDK error types. raise AWSEncryptionSDKClientError(mpl_exception) + # If the provided materials_manager is directly from the MPL, wrap it in a native interface + # for internal use. + elif (self.materials_manager is not None + and isinstance(self.materials_manager, MPL_ICryptographicMaterialsManager)): + self.materials_manager = CryptoMaterialsManagerFromMPL(self.materials_manager) + def _no_mpl_attrs_post_init(self): """If the MPL is NOT present in the runtime, perform post-init logic to validate the new object has a valid state. @@ -593,11 +623,27 @@ def generate_header(self, message_id): if self._encryption_materials.algorithm.message_format_version == 0x02: version = SerializationVersion.V2 + # If the underlying materials_provider provided required_encryption_context_keys + # (ex. if the materials_provider is a required encryption context CMM), + # then partition the encryption context based on those keys. + if hasattr(self._encryption_materials, "required_encryption_context_keys"): + self._required_encryption_context = {} + self._stored_encryption_context = {} + for (key, value) in self._encryption_materials.encryption_context.items(): + if key in self._encryption_materials.required_encryption_context_keys: + self._required_encryption_context[key] = value + else: + self._stored_encryption_context[key] = value + # Otherwise, store all encryption context with the message. + else: + self._stored_encryption_context = self._encryption_materials.encryption_context + self._required_encryption_context = None + kwargs = dict( version=version, algorithm=self._encryption_materials.algorithm, message_id=message_id, - encryption_context=self._encryption_materials.encryption_context, + encryption_context=self._stored_encryption_context, encrypted_data_keys=self._encryption_materials.encrypted_data_keys, content_type=self.content_type, frame_length=self.config.frame_length, @@ -621,13 +667,31 @@ def generate_header(self, message_id): def _write_header(self): """Builds the message header and writes it to the output stream.""" self.output_buffer += serialize_header(header=self._header, signer=self.signer) - self.output_buffer += serialize_header_auth( - version=self._header.version, - algorithm=self._encryption_materials.algorithm, - header=self.output_buffer, - data_encryption_key=self._derived_data_key, - signer=self.signer, - ) + + # If there is _required_encryption_context, + # serialize it, then authenticate it + if hasattr(self, "_required_encryption_context"): + required_ec_serialized = \ + aws_encryption_sdk.internal.formatting.encryption_context.serialize_encryption_context( + self._required_encryption_context + ) + self.output_buffer += serialize_header_auth( + version=self._header.version, + algorithm=self._encryption_materials.algorithm, + header=self.output_buffer, + data_encryption_key=self._derived_data_key, + signer=self.signer, + required_ec_bytes=required_ec_serialized, + ) + # Otherwise, do not pass in any required encryption context + else: + self.output_buffer += serialize_header_auth( + version=self._header.version, + algorithm=self._encryption_materials.algorithm, + header=self.output_buffer, + data_encryption_key=self._derived_data_key, + signer=self.signer, + ) def _prep_non_framed(self): """Prepare the opening data for a non-framed message.""" @@ -825,11 +889,19 @@ class DecryptorConfig(_ClientConfig): :param int max_body_length: Maximum frame size (or content length for non-framed messages) in bytes to read from ciphertext message. + :param dict encryption_context: Dictionary defining encryption context to validate + on decrypt. This is ONLY validated on decrypt if using a CMM + from the aws-cryptographic-material-providers library. """ max_body_length = attr.ib( hash=True, default=None, validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)) ) + encryption_context = attr.ib( + hash=False, # dictionaries are not hashable + default=None, + validator=attr.validators.optional(attr.validators.instance_of(dict)), + ) class StreamDecryptor(_EncryptionStream): # pylint: disable=too-many-instance-attributes @@ -882,6 +954,77 @@ def _prep_message(self): self._prep_non_framed() self._message_prepped = True + def _create_decrypt_materials_request(self, header): + """ + Create a DecryptionMaterialsRequest based on whether + the StreamDecryptor was provided encryption_context on decrypt + (i.e. expects to use a CMM from the MPL). + """ + # If encryption_context is provided on decrypt, + # pass it to the DecryptionMaterialsRequest as reproduced_encryption_context + if hasattr(self.config, "encryption_context") \ + and self.config.encryption_context is not None: + if (_HAS_MPL + and isinstance(self.config.materials_manager, CryptoMaterialsManagerFromMPL)): + return DecryptionMaterialsRequest( + encrypted_data_keys=header.encrypted_data_keys, + algorithm=header.algorithm, + encryption_context=header.encryption_context, + commitment_policy=self.config.commitment_policy, + reproduced_encryption_context=self.config.encryption_context + ) + else: + raise TypeError("encryption_context on decrypt is only supported for CMMs and keyrings " + "from the aws-cryptographic-material-providers library.") + return DecryptionMaterialsRequest( + encrypted_data_keys=header.encrypted_data_keys, + algorithm=header.algorithm, + encryption_context=header.encryption_context, + commitment_policy=self.config.commitment_policy, + ) + + def _validate_parsed_header( + self, + header, + header_auth, + raw_header, + ): + """ + Pass arguments from this StreamDecryptor to validate_header based on whether + the StreamDecryptor has the _required_encryption_context attribute + (i.e. is using the required encryption context CMM from the MPL). + """ + # If _required_encryption_context is present, + # serialize it and pass it to validate_header. + if hasattr(self, "_required_encryption_context") \ + and self._required_encryption_context is not None: + # The authenticated only encryption context is all encryption context key-value pairs where the + # key exists in Required Encryption Context Keys. It is then serialized according to the + # message header Key Value Pairs. + required_ec_serialized = \ + aws_encryption_sdk.internal.formatting.encryption_context.serialize_encryption_context( + self._required_encryption_context + ) + + validate_header( + header=header, + header_auth=header_auth, + # When verifying the header, the AAD input to the authenticated encryption algorithm + # specified by the algorithm suite is the message header body and the serialized + # authenticated only encryption context. + raw_header=raw_header + required_ec_serialized, + data_key=self._derived_data_key + ) + else: + validate_header( + header=header, + header_auth=header_auth, + raw_header=raw_header, + data_key=self._derived_data_key + ) + + return header, header_auth + def _read_header(self): """Reads the message header from the input stream. @@ -908,13 +1051,20 @@ def _read_header(self): ) ) - decrypt_materials_request = DecryptionMaterialsRequest( - encrypted_data_keys=header.encrypted_data_keys, - algorithm=header.algorithm, - encryption_context=header.encryption_context, - commitment_policy=self.config.commitment_policy, - ) + decrypt_materials_request = self._create_decrypt_materials_request(header) decryption_materials = self.config.materials_manager.decrypt_materials(request=decrypt_materials_request) + + # If the materials_manager passed required_encryption_context_keys, + # get the items out of the encryption_context with the keys. + # The items are used in header validation. + if hasattr(decryption_materials, "required_encryption_context_keys"): + self._required_encryption_context = {} + for (key, value) in decryption_materials.encryption_context.items(): + if key in decryption_materials.required_encryption_context_keys: + self._required_encryption_context[key] = value + else: + self._required_encryption_context = None + if decryption_materials.verification_key is None: self.verifier = None else: @@ -953,9 +1103,11 @@ def _read_header(self): "message. Halting processing of this message." ) - validate_header(header=header, header_auth=header_auth, raw_header=raw_header, data_key=self._derived_data_key) - - return header, header_auth + return self._validate_parsed_header( + header=header, + header_auth=header_auth, + raw_header=raw_header, + ) def _prep_non_framed(self): """Prepare the opening data for a non-framed message.""" diff --git a/test/mpl/unit/test_material_managers_mpl_cmm.py b/test/mpl/unit/test_material_managers_mpl_cmm.py index 80d6f00ee..0551e8f30 100644 --- a/test/mpl/unit/test_material_managers_mpl_cmm.py +++ b/test/mpl/unit/test_material_managers_mpl_cmm.py @@ -38,6 +38,7 @@ mock_mpl_cmm = MagicMock(__class__=MPL_ICryptographicMaterialsManager) mock_mpl_encryption_materials = MagicMock(__class__=MPL_EncryptionMaterials) mock_mpl_decrypt_materials = MagicMock(__class__=MPL_DecryptionMaterials) +mock_reproduced_encryption_context = MagicMock(__class_=dict) mock_edk = MagicMock(__class__=Native_EncryptedDataKey) @@ -259,6 +260,7 @@ def test_GIVEN_valid_request_WHEN_create_mpl_decrypt_materials_input_from_reques for mock_edks in [no_mock_edks, one_mock_edk, two_mock_edks]: mock_decryption_materials_request.encrypted_data_keys = mock_edks + mock_decryption_materials_request.reproduced_encryption_context = mock_reproduced_encryption_context # When: _create_mpl_decrypt_materials_input_from_request output = CryptoMaterialsManagerFromMPL._create_mpl_decrypt_materials_input_from_request( @@ -271,6 +273,7 @@ def test_GIVEN_valid_request_WHEN_create_mpl_decrypt_materials_input_from_reques assert output.algorithm_suite_id == mock_algorithm_id assert output.commitment_policy == mock_commitment_policy assert output.encryption_context == mock_decryption_materials_request.encryption_context + assert output.reproduced_encryption_context == mock_reproduced_encryption_context assert len(output.encrypted_data_keys) == len(mock_edks) for i in range(len(output.encrypted_data_keys)): diff --git a/test/mpl/unit/test_material_managers_mpl_materials.py b/test/mpl/unit/test_material_managers_mpl_materials.py index 9e76556a2..8d9052c0a 100644 --- a/test/mpl/unit/test_material_managers_mpl_materials.py +++ b/test/mpl/unit/test_material_managers_mpl_materials.py @@ -160,6 +160,19 @@ def test_GIVEN_valid_signing_key_WHEN_EncryptionMaterials_get_signing_key_THEN_r assert output == mock_signing_key +def test_GIVEN_valid_required_encryption_context_keys_WHEN_EncryptionMaterials_get_required_encryption_context_keys_THEN_returns_required_encryption_context_keys(): # noqa pylint: disable=line-too-long + # Given: valid required encryption context keys + mock_required_encryption_context_keys = MagicMock(__class__=bytes) + mock_mpl_encryption_materials.required_encryption_context_keys = mock_required_encryption_context_keys + + # When: get required encryption context keys + mpl_encryption_materials = EncryptionMaterialsFromMPL(mpl_materials=mock_mpl_encryption_materials) + output = mpl_encryption_materials.required_encryption_context_keys + + # Then: returns required encryption context keys + assert output == mock_required_encryption_context_keys + + def test_GIVEN_valid_data_key_WHEN_DecryptionMaterials_get_data_key_THEN_returns_data_key(): # Given: valid MPL data key mock_data_key = MagicMock(__class__=bytes) @@ -187,3 +200,29 @@ def test_GIVEN_valid_verification_key_WHEN_DecryptionMaterials_get_verification_ # Then: returns verification key assert output == mock_verification_key + + +def test_GIVEN_valid_encryption_context_WHEN_DecryptionMaterials_get_encryption_context_THEN_returns_encryption_context(): # noqa pylint: disable=line-too-long + # Given: valid encryption context + mock_encryption_context = MagicMock(__class__=Dict[str, str]) + mock_mpl_decrypt_materials.encryption_context = mock_encryption_context + + # When: get encryption context + mpl_decryption_materials = DecryptionMaterialsFromMPL(mpl_materials=mock_mpl_decrypt_materials) + output = mpl_decryption_materials.encryption_context + + # Then: returns valid encryption context + assert output == mock_encryption_context + + +def test_GIVEN_valid_required_encryption_context_keys_WHEN_DecryptionMaterials_get_required_encryption_context_keys_THEN_returns_required_encryption_context_keys(): # noqa pylint: disable=line-too-long + # Given: valid required encryption context keys + mock_required_encryption_context_keys = MagicMock(__class__=bytes) + mock_mpl_decrypt_materials.required_encryption_context_keys = mock_required_encryption_context_keys + + # When: get required encryption context keys + mpl_decryption_materials = DecryptionMaterialsFromMPL(mpl_materials=mock_mpl_decrypt_materials) + output = mpl_decryption_materials.required_encryption_context_keys + + # Then: returns required encryption context keys + assert output == mock_required_encryption_context_keys diff --git a/test/unit/test_serialize.py b/test/unit/test_serialize.py index 56da114b4..06ac6126b 100644 --- a/test/unit/test_serialize.py +++ b/test/unit/test_serialize.py @@ -79,6 +79,7 @@ def apply_fixtures(self): "aws_encryption_sdk.internal.formatting.serialize.aws_encryption_sdk.internal.utils.validate_frame_length" ) self.mock_valid_frame_length = self.mock_valid_frame_length_patcher.start() + self.mock_required_ec_bytes = MagicMock() # Set up mock signer self.mock_signer = MagicMock() self.mock_signer.update.return_value = None @@ -167,6 +168,34 @@ def test_serialize_header_auth_v1_no_signer(self): data_encryption_key=VALUES["data_key_obj"], ) + @patch("aws_encryption_sdk.internal.formatting.serialize.header_auth_iv") + def test_GIVEN_required_ec_bytes_WHEN_serialize_header_auth_v1_THEN_aad_has_required_ec_bytes( + self, + mock_header_auth_iv, + ): + """Validate that the _create_header_auth function + behaves as expected for SerializationVersion.V1 + when required_ec_bytes are provided. + """ + self.mock_encrypt.return_value = VALUES["header_auth_base"] + test = aws_encryption_sdk.internal.formatting.serialize.serialize_header_auth( + version=SerializationVersion.V1, + algorithm=self.mock_algorithm, + header=VALUES["serialized_header"], + data_encryption_key=sentinel.encryption_key, + signer=self.mock_signer, + required_ec_bytes=self.mock_required_ec_bytes, + ) + self.mock_encrypt.assert_called_once_with( + algorithm=self.mock_algorithm, + key=sentinel.encryption_key, + plaintext=b"", + associated_data=VALUES["serialized_header"] + self.mock_required_ec_bytes, + iv=mock_header_auth_iv.return_value, + ) + self.mock_signer.update.assert_called_once_with(VALUES["serialized_header_auth"]) + assert test == VALUES["serialized_header_auth"] + @patch("aws_encryption_sdk.internal.formatting.serialize.header_auth_iv") def test_serialize_header_auth_v2(self, mock_header_auth_iv): """Validate that the _create_header_auth function @@ -203,6 +232,33 @@ def test_serialize_header_auth_v2_no_signer(self): data_encryption_key=VALUES["data_key_obj"], ) + @patch("aws_encryption_sdk.internal.formatting.serialize.header_auth_iv") + def test_GIVEN_required_ec_bytes_WHEN_serialize_header_auth_v2_THEN_aad_has_required_ec_bytes( + self, + mock_header_auth_iv, + ): + """Validate that the _create_header_auth function + behaves as expected for SerializationVersion.V2. + """ + self.mock_encrypt.return_value = VALUES["header_auth_base"] + test = aws_encryption_sdk.internal.formatting.serialize.serialize_header_auth( + version=SerializationVersion.V2, + algorithm=self.mock_algorithm, + header=VALUES["serialized_header_v2_committing"], + data_encryption_key=sentinel.encryption_key, + signer=self.mock_signer, + required_ec_bytes=self.mock_required_ec_bytes, + ) + self.mock_encrypt.assert_called_once_with( + algorithm=self.mock_algorithm, + key=sentinel.encryption_key, + plaintext=b"", + associated_data=VALUES["serialized_header_v2_committing"] + self.mock_required_ec_bytes, + iv=mock_header_auth_iv.return_value, + ) + self.mock_signer.update.assert_called_once_with(VALUES["serialized_header_auth_v2"]) + assert test == VALUES["serialized_header_auth_v2"] + def test_serialize_non_framed_open(self): """Validate that the serialize_non_framed_open function behaves as expected. diff --git a/test/unit/test_streaming_client_configs.py b/test/unit/test_streaming_client_configs.py index 18886f65b..435aff0da 100644 --- a/test/unit/test_streaming_client_configs.py +++ b/test/unit/test_streaming_client_configs.py @@ -15,7 +15,7 @@ import pytest import six -from mock import patch +from mock import MagicMock, patch from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.internal.defaults import ALGORITHM, FRAME_LENGTH, LINE_LENGTH @@ -33,7 +33,7 @@ # Ideally, this logic would be based on mocking imports and testing logic, # but doing that introduces errors that cause other tests to fail. try: - from aws_cryptographic_materialproviders.mpl.references import IKeyring + from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring HAS_MPL = True from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL @@ -236,24 +236,28 @@ def test_client_configs_with_mpl( assert test.materials_manager is not None # If materials manager was provided, it should be directly used - if hasattr(kwargs, "materials_manager"): + if "materials_manager" in kwargs: assert kwargs["materials_manager"] == test.materials_manager + # If native key_provider was provided, it should be wrapped in native materials manager + elif "key_provider" in kwargs: + assert test.key_provider is not None + assert test.key_provider == kwargs["key_provider"] + assert isinstance(test.materials_manager, DefaultCryptoMaterialsManager) + # If MPL keyring was provided, it should be wrapped in MPL materials manager - if hasattr(kwargs, "keyring"): + elif "keyring" in kwargs: assert test.keyring is not None assert test.keyring == kwargs["keyring"] assert isinstance(test.keyring, IKeyring) assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) - # If native key_provider was provided, it should be wrapped in native materials manager - if hasattr(kwargs, "key_provider"): - assert test.key_provider is not None - assert test.key_provider == kwargs["key_provider"] - assert isinstance(test.materials_manager, DefaultCryptoMaterialsManager) + else: + raise ValueError(f"Test did not find materials_manager or key_provider. {kwargs}") -# This needs its own test; pytest parametrize cannot use a conditionally-loaded type +# This is an addition to test_client_configs_with_mpl; +# This needs its own test; pytest's parametrize cannot use a conditionally-loaded type (IKeyring) @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") def test_keyring_client_config_with_mpl( ): @@ -265,16 +269,30 @@ def test_keyring_client_config_with_mpl( test = _ClientConfig(**kwargs) - # In all cases, config should have a materials manager assert test.materials_manager is not None - # If materials manager was provided, it should be directly used - if hasattr(kwargs, "materials_manager"): - assert kwargs["materials_manager"] == test.materials_manager + assert test.keyring is not None + assert test.keyring == kwargs["keyring"] + assert isinstance(test.keyring, IKeyring) + assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) - # If MPL keyring was provided, it should be wrapped in MPL materials manager - if hasattr(kwargs, "keyring"): - assert test.keyring is not None - assert test.keyring == kwargs["keyring"] - assert isinstance(test.keyring, IKeyring) - assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) + +# This is an addition to test_client_configs_with_mpl; +# This needs its own test; pytest's parametrize cannot use a conditionally-loaded type (MPL CMM) +@pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") +def test_mpl_cmm_client_config_with_mpl( +): + mock_mpl_cmm = MagicMock(__class__=ICryptographicMaterialsManager) + kwargs = { + "source": b"", + "materials_manager": mock_mpl_cmm, + "commitment_policy": CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + } + + test = _ClientConfig(**kwargs) + + assert test.materials_manager is not None + # Assert that the MPL CMM is wrapped in the native interface + assert isinstance(test.materials_manager, CryptoMaterialsManagerFromMPL) + # Assert the MPL CMM is used by the native interface + assert test.materials_manager.mpl_cmm == mock_mpl_cmm diff --git a/test/unit/test_streaming_client_stream_decryptor.py b/test/unit/test_streaming_client_stream_decryptor.py index e06cad308..ce3d6ee3c 100644 --- a/test/unit/test_streaming_client_stream_decryptor.py +++ b/test/unit/test_streaming_client_stream_decryptor.py @@ -11,6 +11,7 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Unit test suite for aws_encryption_sdk.streaming_client.StreamDecryptor""" +# noqa pylint: disable=too-many-lines import io import pytest @@ -193,6 +194,10 @@ def test_read_header(self, mock_derive_datakey, mock_decrypt_materials_request, test_decryptor.source_stream = ct_stream test_decryptor._stream_length = len(VALUES["data_128"]) + # Mock: hasattr(self.config, "encryption_context") returns False + if hasattr(test_decryptor.config, "encryption_context"): + del test_decryptor.config.encryption_context + test_header, test_header_auth = test_decryptor._read_header() self.mock_deserialize_header.assert_called_once_with(ct_stream, None) @@ -293,6 +298,39 @@ def test_GIVEN_verification_key_AND_has_mpl_AND_not_MPLCMM_WHEN_read_header_THEN algorithm=self.mock_header.algorithm, key_bytes=sentinel.verification_key ) + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.Verifier") + # Given: no MPL + @pytest.mark.skipif(HAS_MPL, reason="Test should only be executed without MPL in installation") + def test_GIVEN_decrypt_config_has_ec_AND_no_mpl_WHEN_read_header_THEN_raise_TypeError( + self, + mock_verifier, + mock_decrypt_materials_request, + *_, + ): + + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + ct_stream = io.BytesIO(VALUES["data_128"]) + mock_commitment_policy = MagicMock(__class__=CommitmentPolicy) + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=ct_stream, + commitment_policy=mock_commitment_policy, + ) + test_decryptor.source_stream = ct_stream + test_decryptor._stream_length = len(VALUES["data_128"]) + # Given: self.config has "encryption_context" + # (i.e. encryption context provided on decrypt) + any_reproduced_ec = {"some": "ec"} + test_decryptor.config.encryption_context = any_reproduced_ec + + # Then: raise TypeError + with pytest.raises(TypeError): + # When: read header + test_decryptor._read_header() + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") @patch("aws_encryption_sdk.streaming_client.Verifier") @@ -882,3 +920,219 @@ def test_close_no_footer(self, mock_close): with pytest.raises(SerializationError) as excinfo: test_decryptor.close() excinfo.match("Footer not read") + + @patch("aws_encryption_sdk.streaming_client.validate_header") + def test_GIVEN_does_not_have_required_EC_WHEN_validate_parsed_header_THEN_validate_header( + self, + mock_validate_header + ): + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + test_decryptor._derived_data_key = sentinel.derived_data_key + # Given: test_decryptor does not have _required_encryption_context attribute + # When: _validate_parsed_header + test_decryptor._validate_parsed_header( + header=self.mock_header, + header_auth=sentinel.header_auth, + raw_header=self.mock_raw_header + ) + # Then: validate_header + mock_validate_header.assert_called_once_with( + header=self.mock_header, + header_auth=sentinel.header_auth, + raw_header=self.mock_raw_header, + data_key=sentinel.derived_data_key, + ) + + @patch("aws_encryption_sdk.internal.formatting.encryption_context.serialize_encryption_context") + @patch("aws_encryption_sdk.streaming_client.validate_header") + def test_GIVEN_has_required_EC_WHEN_validate_parsed_header_THEN_validate_header_with_serialized_required_EC( + self, + mock_validate_header, + mock_serialize_encryption_context, + ): + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + test_decryptor._derived_data_key = sentinel.derived_data_key + # Given: test_decryptor has _required_encryption_context attribute + mock_required_ec = MagicMock(__class__=dict) + test_decryptor._required_encryption_context = mock_required_ec + mock_serialized_required_ec = MagicMock(__class__=bytes) + mock_serialize_encryption_context.return_value = mock_serialized_required_ec + # When: _validate_parsed_header + test_decryptor._validate_parsed_header( + header=self.mock_header, + header_auth=sentinel.header_auth, + raw_header=self.mock_raw_header + ) + # Then: call validate_header with serialized required EC + mock_validate_header.assert_called_once_with( + header=self.mock_header, + header_auth=sentinel.header_auth, + raw_header=self.mock_raw_header + mock_serialized_required_ec, + data_key=sentinel.derived_data_key, + ) + + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_MPL_AND_config_has_EC_WHEN_create_decrypt_materials_request_THEN_provide_reproduced_EC( + self, + ): + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_mpl_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + + # Given: StreamDecryptor.config has encryption_context attribute + mock_reproduced_encryption_context = MagicMock(__class__=dict) + test_decryptor.config.encryption_context = mock_reproduced_encryption_context + # Type checking on header encryption context seems to require concrete instance, + # neither MagicMock nor sentinel value work + self.mock_header.encryption_context = {"some_key_to_pass_type_validation": "some_value"} + + # When: _create_decrypt_materials_request + output = test_decryptor._create_decrypt_materials_request( + header=self.mock_header, + ) + + # Then: decrypt_materials_request has reproduced_encryption_context attribute + assert hasattr(output, "reproduced_encryption_context") + assert output.reproduced_encryption_context == mock_reproduced_encryption_context + + def test_GIVEN_config_does_not_have_EC_WHEN_create_decrypt_materials_request_THEN_request_does_not_have_reproduced_EC( # noqa pylint: disable=line-too-long + self, + ): + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + + # Given: StreamDecryptor.config does not have an encryption_context attribute + del test_decryptor.config.encryption_context + # Type checking on header encryption context seems to require concrete instance, + # neither MagicMock nor sentinel value work + self.mock_header.encryption_context = {"some_key_to_pass_type_validation": "some_value"} + + # When: _create_decrypt_materials_request + output = test_decryptor._create_decrypt_materials_request( + header=self.mock_header, + ) + + # Then: decrypt_materials_request.reproduced_encryption_context is None + assert output.reproduced_encryption_context is None + + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.Verifier") + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_materials_has_no_required_encryption_context_keys_attr_WHEN_read_header_THEN_required_EC_is_None( + self, + mock_verifier, + *_ + ): + + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + + # Given: decryption_materials does not have a required_encryption_context_keys attribute + del self.mock_decrypt_materials.required_encryption_context_keys + + # When: _read_header + test_decryptor._read_header() + + # Then: StreamDecryptor._required_encryption_context is None + assert test_decryptor._required_encryption_context is None + + @patch("aws_encryption_sdk.streaming_client.derive_data_encryption_key") + @patch("aws_encryption_sdk.streaming_client.DecryptionMaterialsRequest") + @patch("aws_encryption_sdk.streaming_client.Verifier") + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_materials_has_required_encryption_context_keys_attr_WHEN_read_header_THEN_creates_correct_required_EC( # noqa pylint: disable=line-too-long + self, + mock_verifier, + *_ + ): + required_encryption_context_keys_values = [ + # Case of empty encryption context list is not allowed; + # if a list is provided, it must be non-empty. + # The MPL enforces this behavior on construction. + ["one_key"], + ["one_key", "two_key"], + ["one_key", "two_key", "red_key"], + ["one_key", "two_key", "red_key", "blue_key"], + ] + + encryption_context_values = [ + {}, + {"one_key": "some_value"}, + { + "one_key": "some_value", + "two_key": "some_other_value", + }, + { + "one_key": "some_value", + "two_key": "some_other_value", + "red_key": "some_red_value", + }, + { + "one_key": "some_value", + "two_key": "some_other_value", + "red_key": "some_red_value", + "blue_key": "some_blue_value", + } + ] + + for required_encryption_context_keys in required_encryption_context_keys_values: + + # Given: decryption_materials has required_encryption_context_keys + self.mock_decrypt_materials.required_encryption_context_keys = \ + required_encryption_context_keys + + for encryption_context in encryption_context_values: + + self.mock_decrypt_materials.encryption_context = encryption_context + + mock_verifier_instance = MagicMock() + mock_verifier.from_key_bytes.return_value = mock_verifier_instance + + self.mock_header.content_type = ContentType.FRAMED_DATA + test_decryptor = StreamDecryptor( + materials_manager=self.mock_materials_manager, + source=self.mock_input_stream, + commitment_policy=self.mock_commitment_policy, + ) + + # When: _read_header + test_decryptor._read_header() + + # Then: Assert correctness of partitioned EC + for k, v in encryption_context.items(): + # If a key is in required_encryption_context_keys, then ... + if k in required_encryption_context_keys: + # ... its EC is in the StreamEncryptor._required_encryption_context + assert k in test_decryptor._required_encryption_context + assert test_decryptor._required_encryption_context[k] == v + # If a key is NOT in required_encryption_context_keys, then ... + else: + # ... its EC is NOT in the StreamEncryptor._required_encryption_context + assert k not in test_decryptor._required_encryption_context diff --git a/test/unit/test_streaming_client_stream_encryptor.py b/test/unit/test_streaming_client_stream_encryptor.py index e43752689..4df79e146 100644 --- a/test/unit/test_streaming_client_stream_encryptor.py +++ b/test/unit/test_streaming_client_stream_encryptor.py @@ -11,6 +11,7 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Unit test suite for aws_encryption_sdk.streaming_client.StreamEncryptor""" +# noqa pylint: disable=too-many-lines import io import pytest @@ -451,6 +452,119 @@ def test_GIVEN_has_mpl_AND_has_MPLCMM_AND_uses_signer_WHEN_prep_message_THEN_sig encoding=serialization.Encoding.PEM ) + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_mpl_AND_encryption_materials_has_required_EC_keys_WHEN_prep_message_THEN_paritions_stored_and_required_EC( # noqa pylint: disable=line-too-long + self + ): + # Create explicit values to explicitly test logic in smaller cases + required_encryption_context_keys_values = [ + # Case of empty encryption context list is not allowed; + # if a list is provided, it must be non-empty. + # The MPL enforces this behavior on construction. + ["one_key"], + ["one_key", "two_key"], + ["one_key", "two_key", "red_key"], + ["one_key", "two_key", "red_key", "blue_key"], + ] + + encryption_context_values = [ + {}, + {"one_key": "some_value"}, + { + "one_key": "some_value", + "two_key": "some_other_value", + }, + { + "one_key": "some_value", + "two_key": "some_other_value", + "red_key": "some_red_value", + }, + { + "one_key": "some_value", + "two_key": "some_other_value", + "red_key": "some_red_value", + "blue_key": "some_blue_value", + } + ] + + self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 + + for required_encryption_context_keys in required_encryption_context_keys_values: + + # Given: encryption context has required_encryption_context_keys + self.mock_encryption_materials.required_encryption_context_keys = \ + required_encryption_context_keys + + for encryption_context in encryption_context_values: + self.mock_encryption_materials.encryption_context = encryption_context + + test_encryptor = StreamEncryptor( + source=VALUES["data_128"], + materials_manager=self.mock_mpl_materials_manager, + frame_length=self.mock_frame_length, + algorithm=Algorithm.AES_128_GCM_IV12_TAG16, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.content_type = ContentType.FRAMED_DATA + # When: prep_message + test_encryptor._prep_message() + + # Then: Assert correctness of partitioned EC + for k, v in encryption_context.items(): + # If a key is in required_encryption_context_keys, then + if k in required_encryption_context_keys: + # 1) Its EC is in the StreamEncryptor._required_encryption_context + assert k in test_encryptor._required_encryption_context + assert test_encryptor._required_encryption_context[k] == v + # 2) Its EC is NOT in the StreamEncryptor._stored_encryption_context + assert k not in test_encryptor._stored_encryption_context + # If a key is NOT in required_encryption_context_keys, then + else: + # 1) Its EC is NOT in the StreamEncryptor._required_encryption_context + assert k not in test_encryptor._required_encryption_context + # 2) Its EC is in the StreamEncryptor._stored_encryption_context + assert k in test_encryptor._stored_encryption_context + assert test_encryptor._stored_encryption_context[k] == v + + # Assert size(stored_EC) + size(required_EC) == size(EC) + # (i.e. every EC was sorted into one or the other) + assert len(test_encryptor._required_encryption_context) \ + + len(test_encryptor._stored_encryption_context) \ + == len(encryption_context) + + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_mpl_AND_encryption_materials_does_not_have_required_EC_keys_WHEN_prep_message_THEN_stored_EC_is_EC( # noqa pylint: disable=line-too-long + self + ): + + self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 + + mock_encryption_context = MagicMock(__class__=dict) + self.mock_encryption_materials.encryption_context = mock_encryption_context + # Given: encryption materials does not have required encryption context keys + # (MagicMock default is to "make up" "Some" value here; this deletes that value) + del self.mock_encryption_materials.required_encryption_context_keys + + test_encryptor = StreamEncryptor( + source=VALUES["data_128"], + materials_manager=self.mock_mpl_materials_manager, + frame_length=self.mock_frame_length, + algorithm=Algorithm.AES_128_GCM_IV12_TAG16, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.content_type = ContentType.FRAMED_DATA + # When: prep_message + test_encryptor._prep_message() + + # Then: _stored_encryption_context is the provided encryption_context + assert test_encryptor._stored_encryption_context == mock_encryption_context + # Then: _required_encryption_context is None + assert test_encryptor._required_encryption_context is None + def test_prep_message_no_signer(self): self.mock_encryption_materials.algorithm = Algorithm.AES_128_GCM_IV12_TAG16 test_encryptor = StreamEncryptor( @@ -575,6 +689,53 @@ def test_write_header(self): ) assert test_encryptor.output_buffer == b"1234567890" + @patch("aws_encryption_sdk.internal.formatting.encryption_context.serialize_encryption_context") + # Given: has MPL + @pytest.mark.skipif(not HAS_MPL, reason="Test should only be executed with MPL in installation") + def test_GIVEN_has_mpl_AND_has_required_EC_WHEN_write_header_THEN_adds_serialized_required_ec_to_header_auth( + self, + serialize_encryption_context + ): + self.mock_serialize_header.return_value = b"12345" + self.mock_serialize_header_auth.return_value = b"67890" + pt_stream = io.BytesIO(self.plaintext) + test_encryptor = StreamEncryptor( + source=pt_stream, + materials_manager=self.mock_materials_manager, + algorithm=aws_encryption_sdk.internal.defaults.ALGORITHM, + frame_length=self.mock_frame_length, + commitment_policy=self.mock_commitment_policy, + signature_policy=self.mock_signature_policy, + ) + test_encryptor.signer = sentinel.signer + test_encryptor.content_type = sentinel.content_type + test_encryptor._header = sentinel.header + sentinel.header.version = SerializationVersion.V1 + test_encryptor.output_buffer = b"" + test_encryptor._encryption_materials = self.mock_encryption_materials + test_encryptor._derived_data_key = sentinel.derived_data_key + + # Given: StreamEncryptor has _required_encryption_context + mock_required_ec = MagicMock(__class__=dict) + test_encryptor._required_encryption_context = mock_required_ec + mock_serialized_required_ec = MagicMock(__class__=bytes) + serialize_encryption_context.return_value = mock_serialized_required_ec + + # When: _write_header() + test_encryptor._write_header() + + self.mock_serialize_header.assert_called_once_with(header=test_encryptor._header, signer=sentinel.signer) + self.mock_serialize_header_auth.assert_called_once_with( + version=sentinel.header.version, + algorithm=self.mock_encryption_materials.algorithm, + header=b"12345", + data_encryption_key=sentinel.derived_data_key, + signer=sentinel.signer, + # Then: Pass serialized required EC to serialize_header_auth + required_ec_bytes=mock_serialized_required_ec, + ) + assert test_encryptor.output_buffer == b"1234567890" + @patch("aws_encryption_sdk.streaming_client.non_framed_body_iv") def test_prep_non_framed(self, mock_non_framed_iv): self.mock_serialize_non_framed_open.return_value = b"1234567890" diff --git a/test_vector_handlers/test/aws-crypto-tools-test-vector-framework b/test_vector_handlers/test/aws-crypto-tools-test-vector-framework index c3d73fae2..9eb2fcbbe 160000 --- a/test_vector_handlers/test/aws-crypto-tools-test-vector-framework +++ b/test_vector_handlers/test/aws-crypto-tools-test-vector-framework @@ -1 +1 @@ -Subproject commit c3d73fae260fd9e9cc9e746f09a7ffbab83576e2 +Subproject commit 9eb2fcbbe47ab30c29d6ad9a8125b1064e0db42a From 91d06aea6426889d69dc7f89b5ffdba17c9c0208 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 30 Apr 2024 15:36:43 -0700 Subject: [PATCH 03/51] chore: Merge from master (#670) --- .github/workflows/ci_test-vector-handler.yaml | 4 +- .github/workflows/ci_tests.yaml | 4 +- appveyor.yml | 113 ------------------ src/aws_encryption_sdk/__init__.py | 2 +- 4 files changed, 5 insertions(+), 118 deletions(-) delete mode 100644 appveyor.yml diff --git a/.github/workflows/ci_test-vector-handler.yaml b/.github/workflows/ci_test-vector-handler.yaml index 2fcd22fc9..8a142096d 100644 --- a/.github/workflows/ci_test-vector-handler.yaml +++ b/.github/workflows/ci_test-vector-handler.yaml @@ -19,7 +19,7 @@ jobs: os: - ubuntu-latest - windows-latest - - macos-latest + - macos-12 python: - 3.8 - 3.x @@ -34,7 +34,7 @@ jobs: # x86 builds are only meaningful for Windows - os: ubuntu-latest architecture: x86 - - os: macos-latest + - os: macos-12 architecture: x86 steps: - uses: aws-actions/configure-aws-credentials@v4 diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index 3187b8db0..b03c47163 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -30,7 +30,7 @@ jobs: # (i.e. doo files, per-package module names) # Disable for now # - windows-latest - - macos-latest + - macos-12 python: - 3.7 - 3.8 @@ -59,7 +59,7 @@ jobs: # x86 builds are only meaningful for Windows - os: ubuntu-latest architecture: x86 - - os: macos-latest + - os: macos-12 architecture: x86 # MPL is not supported on <3.11 - python: 3.7 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index cfb4bdcdb..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,113 +0,0 @@ -# https://packaging.python.org/guides/supporting-windows-using-appveyor/ - -environment: - - matrix: - # The only test we perform on Windows are our actual code tests. All linting, static - # analysis, etc are only run on Linux (via Travis CI). - - # Python 2.7 - - PYTHON: "C:\\Python27" - TOXENV: "py27-local" - - PYTHON: "C:\\Python27" - TOXENV: "py27-integ" - - PYTHON: "C:\\Python27" - TOXENV: "py27-accept" - - PYTHON: "C:\\Python27" - TOXENV: "py27-examples" - - PYTHON: "C:\\Python27-x64" - TOXENV: "py27-local" - - PYTHON: "C:\\Python27-x64" - TOXENV: "py27-integ" - - PYTHON: "C:\\Python27-x64" - TOXENV: "py27-accept" - - PYTHON: "C:\\Python27-x64" - TOXENV: "py27-examples" - - # Python 3.4 - - PYTHON: "C:\\Python34" - TOXENV: "py34-local" - - PYTHON: "C:\\Python34" - TOXENV: "py34-integ" - - PYTHON: "C:\\Python34" - TOXENV: "py34-accept" - - PYTHON: "C:\\Python34" - TOXENV: "py34-examples" - - PYTHON: "C:\\Python34-x64" - DISTUTILS_USE_SDK: "1" - TOXENV: "py34-local" - - PYTHON: "C:\\Python34-x64" - DISTUTILS_USE_SDK: "1" - TOXENV: "py34-integ" - - PYTHON: "C:\\Python34-x64" - DISTUTILS_USE_SDK: "1" - TOXENV: "py34-accept" - - PYTHON: "C:\\Python34-x64" - DISTUTILS_USE_SDK: "1" - TOXENV: "py34-examples" - - # Python 3.5 - - PYTHON: "C:\\Python35" - TOXENV: "py35-local" - - PYTHON: "C:\\Python35" - TOXENV: "py35-integ" - - PYTHON: "C:\\Python35" - TOXENV: "py35-accept" - - PYTHON: "C:\\Python35" - TOXENV: "py35-examples" - - PYTHON: "C:\\Python35-x64" - TOXENV: "py35-local" - - PYTHON: "C:\\Python35-x64" - TOXENV: "py35-integ" - - PYTHON: "C:\\Python35-x64" - TOXENV: "py35-accept" - - PYTHON: "C:\\Python35-x64" - TOXENV: "py35-examples" - - # Python 3.6 - - PYTHON: "C:\\Python36" - TOXENV: "py36-local" - - PYTHON: "C:\\Python36" - TOXENV: "py36-integ" - - PYTHON: "C:\\Python36" - TOXENV: "py36-accept" - - PYTHON: "C:\\Python36" - TOXENV: "py36-examples" - - PYTHON: "C:\\Python36-x64" - TOXENV: "py36-local" - - PYTHON: "C:\\Python36-x64" - TOXENV: "py36-integ" - - PYTHON: "C:\\Python36-x64" - TOXENV: "py36-accept" - - PYTHON: "C:\\Python36-x64" - TOXENV: "py36-examples" - - # Python 3.7 - - PYTHON: "C:\\Python37" - TOXENV: "py37-local" - - PYTHON: "C:\\Python37" - TOXENV: "py37-integ" - - PYTHON: "C:\\Python37" - TOXENV: "py37-accept" - - PYTHON: "C:\\Python37" - TOXENV: "py37-examples" - - PYTHON: "C:\\Python37-x64" - TOXENV: "py37-local" - - PYTHON: "C:\\Python37-x64" - TOXENV: "py37-integ" - - PYTHON: "C:\\Python37-x64" - TOXENV: "py37-accept" - - PYTHON: "C:\\Python37-x64" - TOXENV: "py37-examples" - -install: - # Prepend newly installed Python to the PATH of this build - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - # Check the Python version to verify the correct version was installed - - "python --version" - - "python -m pip install wheel tox" - -build: off - -test_script: - - "tox" diff --git a/src/aws_encryption_sdk/__init__.py b/src/aws_encryption_sdk/__init__.py index 74732bfc5..66b779fa5 100644 --- a/src/aws_encryption_sdk/__init__.py +++ b/src/aws_encryption_sdk/__init__.py @@ -164,7 +164,7 @@ def decrypt(self, **kwargs): ... 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', ... 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' ... ]) - >>> my_ciphertext, encryptor_header = client.decrypt( + >>> my_plaintext, decryptor_header = client.decrypt( ... source=my_ciphertext, ... key_provider=kms_key_provider ... ) From 750bb6843084d5f4ac57d561e06216a9a3305fd8 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Thu, 2 May 2024 12:22:45 -0700 Subject: [PATCH 04/51] chore: Added KMS keyring example (#659) --- .../src/keyrings/aws_kms_keyring_example.py | 119 ++++++++++++++++++ .../test_i_aws_kms_keyring_example.py | 14 +++ .../keyrings/test_i_hierarchical_keyring.py | 5 +- 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 examples/src/keyrings/aws_kms_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_keyring_example.py diff --git a/examples/src/keyrings/aws_kms_keyring_example.py b/examples/src/keyrings/aws_kms_keyring_example.py new file mode 100644 index 000000000..fa7ffd12f --- /dev/null +++ b/examples/src/keyrings/aws_kms_keyring_example.py @@ -0,0 +1,119 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the KMS Keyring + +The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and +decrypt data keys. This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +AWS KMS keyrings can be used independently or in a multi-keyring with other keyrings +of the same or a different type. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS keyring. + + Usage: encrypt_and_decrypt_with_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # 5. Encrypt the data with the encryptionContext. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=kms_keyring, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=kms_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/test/keyrings/test_i_aws_kms_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_keyring_example.py new file mode 100644 index 000000000..83a784a9e --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_keyring_example.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS Keyring example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_keyring(kms_key_id) diff --git a/examples/test/keyrings/test_i_hierarchical_keyring.py b/examples/test/keyrings/test_i_hierarchical_keyring.py index c4583534a..5a3adaa1c 100644 --- a/examples/test/keyrings/test_i_hierarchical_keyring.py +++ b/examples/test/keyrings/test_i_hierarchical_keyring.py @@ -9,6 +9,7 @@ def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS Hierarchical Keyring example.""" key_store_table_name = "KeyStoreDdbTable" - key_arn = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126" - encrypt_and_decrypt_with_keyring(key_store_table_name, key_store_table_name, key_arn) + kms_key_id = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126" + encrypt_and_decrypt_with_keyring(key_store_table_name, key_store_table_name, kms_key_id) From 88e6d586453597eb8eb055068c6e1a029362967d Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Thu, 2 May 2024 15:13:32 -0700 Subject: [PATCH 05/51] chore: added raw rsa and raw aes keyring examples (#661) --- .gitignore | 2 + .../src/keyrings/raw_aes_keyring_example.py | 129 +++++++++ .../src/keyrings/raw_rsa_keyring_example.py | 249 ++++++++++++++++++ .../test_i_raw_aes_keyring_example.py | 13 + .../test_i_raw_rsa_keyring_example.py | 116 ++++++++ .../materials_managers/mpl/cmm.py | 7 +- 6 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 examples/src/keyrings/raw_aes_keyring_example.py create mode 100644 examples/src/keyrings/raw_rsa_keyring_example.py create mode 100644 examples/test/keyrings/test_i_raw_aes_keyring_example.py create mode 100644 examples/test/keyrings/test_i_raw_rsa_keyring_example.py diff --git a/.gitignore b/.gitignore index fc224adc4..78bc3d5b8 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ __pycache__ # PyTest .pytest_cache +# Ignore key materials generated by examples or tests +test_keys/ # PyCharm .idea/ diff --git a/examples/src/keyrings/raw_aes_keyring_example.py b/examples/src/keyrings/raw_aes_keyring_example.py new file mode 100644 index 000000000..ee0ab7618 --- /dev/null +++ b/examples/src/keyrings/raw_aes_keyring_example.py @@ -0,0 +1,129 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the Raw AES Keyring + +The Raw AES keyring lets you use an AES symmetric key that you provide as a wrapping key that +protects your data key. You need to generate, store, and protect the key material, +preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring +when you need to provide the wrapping key and encrypt the data keys locally or offline. + +This example creates a Raw AES Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +The Raw AES keyring encrypts data by using the AES-GCM algorithm and a wrapping key that +you specify as a byte array. You can specify only one wrapping key in each Raw AES keyring, +but you can include multiple Raw AES keyrings, alone or with other keyrings, in a multi-keyring. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html +""" +import secrets +import sys + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring(): + """Demonstrate an encrypt/decrypt cycle using a Raw AES keyring. + + Usage: encrypt_and_decrypt_with_keyring() + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. The key namespace and key name are defined by you. + # and are used by the Raw AES keyring to determine + # whether it should attempt to decrypt an encrypted data key. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Generate a 256-bit AES key to use with your keyring. + # In practice, you should get this key from a secure key management system such as an HSM. + + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + static_key = secrets.token_bytes(32) + + # 5. Create a Raw AES keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + # 6. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_aes_keyring, + encryption_context=encryption_context + ) + + # 7. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 8. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=raw_aes_keyring + ) + + # 9. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/raw_rsa_keyring_example.py b/examples/src/keyrings/raw_rsa_keyring_example.py new file mode 100644 index 000000000..49d868a86 --- /dev/null +++ b/examples/src/keyrings/raw_rsa_keyring_example.py @@ -0,0 +1,249 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the Raw RSA Keyring + +The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory +with RSA public and private keys that you provide. In this example, we define the RSA keys to +encrypt and decrypt the data keys. + +You need to generate, store, and protect the private key, preferably in a +hardware security module (HSM) or key management system. +The encryption function encrypts the data key under the RSA public key. The decryption function +decrypts the data key using the private key. + +This example creates a Raw RSA Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +4. The original ciphertext is not decryptable using a keyring with a different RSA key pair +These sanity checks are for demonstration in the example only. You do not need these in your code. + +A Raw RSA keyring that encrypts and decrypts must include an asymmetric public key and private +key pair. However, you can encrypt data with a Raw RSA keyring that has only a public key, +and you can decrypt data with a Raw RSA keyring that has only a private key. This example requires +the user to either provide both private and public keys, or not provide any keys and the example +generates both to test encryption and decryption. If you configure a Raw RSA keyring with a +public and private key, be sure that they are part of the same key pair. Some language +implementations of the AWS Encryption SDK will not construct a Raw RSA keyring with keys +from different pairs. Others rely on you to verify that your keys are from the same key pair. +You can include any Raw RSA keyring in a multi-keyring. + +For more information on how to use Raw RSA keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html +""" +import sys + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def should_generate_new_rsa_key_pair(public_key_file_name, private_key_file_name): + """Returns True if user doesn't provide keys, and we need to generate them; + Returns False if the user has already provided both public and private keys + Raises a ValueError if the user only provides one of private_key and public_key + + Usage: should_generate_new_rsa_key_pair(public_key_file_name, private_key_file_name) + """ + # If only one of public_key and private_key files is provided, raise a ValueError + if (public_key_file_name and not private_key_file_name)\ + or (not public_key_file_name and private_key_file_name): + raise ValueError("Either both public and private keys should be provided! Or no keys \ + should be provided and the example can create the keys for you!") + + # If no keys are provided, we should generate a new rsa key pair, so return True + if not public_key_file_name and not private_key_file_name: + return True + + # If both keys are already provided, return False + return False + + +def generate_rsa_keys(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +def create_rsa_keyring(public_key, private_key): + """Create a Raw RSA keyring using the key pair + + Usage: create_rsa_keyring(public_key, private_key) + """ + # 1. The key namespace and key name are defined by you. + # and are used by the Raw RSA keyring + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html + key_name_space = "Some managed raw keys" + key_name = "My 4096-bit RSA wrapping key" + + # 2. Create a Raw RSA keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + raw_rsa_keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return raw_rsa_keyring + + +def encrypt_and_decrypt_with_keyring(public_key_file_name=None, private_key_file_name=None): + """Demonstrate an encrypt/decrypt cycle using a Raw RSA keyring + with user defined keys. If no keys are present, generate new RSA + public and private keys and use them to create a Raw RSA keyring + + Usage: encrypt_and_decrypt_with_keyring(public_key_file_name, private_key_file_name) + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create a Raw RSA keyring. + # If you have provided keys in a PEM file, they will be loaded into the keyring. + # Otherwise, a key pair will be randomly generated for you. + + # Check if we need to generate an RSA key pair + should_generate_new_rsa_key_pair_bool = \ + should_generate_new_rsa_key_pair(public_key_file_name=public_key_file_name, + private_key_file_name=private_key_file_name) + + # If user doesn't provide the keys, that is, if should_generate_new_rsa_key_pair_bool is True + # generate a new RSA public and private key pair + if should_generate_new_rsa_key_pair_bool: + public_key, private_key = generate_rsa_keys() + else: + # If user provides the keys, read the keys from the files + with open(public_key_file_name, "r", encoding='utf-8') as f: + public_key = f.read() + + # Convert the public key from a string to bytes + public_key = bytes(public_key, 'utf-8') + + with open(private_key_file_name, "r", encoding='utf-8') as f: + private_key = f.read() + + # Convert the private key from a string to bytes + private_key = bytes(private_key, 'utf-8') + + # Create the keyring + raw_rsa_keyring = create_rsa_keyring(public_key=public_key, private_key=private_key) + + # 4. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_rsa_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=raw_rsa_keyring + ) + + # 7. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA + + # The next part of the example creates a new RSA keyring (for Bob) to demonstrate that + # decryption of the original ciphertext is not possible with a different keyring (Bob's). + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 9. Create a new Raw RSA keyring for Bob + # Generate new keys + public_key_bob, private_key_bob = generate_rsa_keys() + + # Create the keyring + raw_rsa_keyring_bob = create_rsa_keyring(public_key=public_key_bob, private_key=private_key_bob) + + # 10. Test decrypt for the original ciphertext using raw_rsa_keyring_bob + try: + plaintext_bytes_bob, _ = client.decrypt( + source=ciphertext, + keyring=raw_rsa_keyring_bob + ) + + raise AssertionError("client.decrypt should throw an error of type AWSEncryptionSDKClientError!") + except AWSEncryptionSDKClientError: + pass diff --git a/examples/test/keyrings/test_i_raw_aes_keyring_example.py b/examples/test/keyrings/test_i_raw_aes_keyring_example.py new file mode 100644 index 000000000..e5bd6d4c2 --- /dev/null +++ b/examples/test/keyrings/test_i_raw_aes_keyring_example.py @@ -0,0 +1,13 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw AES keyring example.""" +import pytest + +from ...src.keyrings.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the Raw AES Keyring example.""" + encrypt_and_decrypt_with_keyring() diff --git a/examples/test/keyrings/test_i_raw_rsa_keyring_example.py b/examples/test/keyrings/test_i_raw_rsa_keyring_example.py new file mode 100644 index 000000000..e036eb0b0 --- /dev/null +++ b/examples/test/keyrings/test_i_raw_rsa_keyring_example.py @@ -0,0 +1,116 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw RSA keyring example.""" +import os + +import pytest + +from ...src.keyrings.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring, generate_rsa_keys + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring_without_user_defined_keys(): + """Test function for encrypt and decrypt using the Raw RSA Keyring example. + + Here user doesn't provide the public and private keys + """ + encrypt_and_decrypt_with_keyring() + + +def test_encrypt_and_decrypt_with_keyring_with_user_defined_keys(): + """Test function for encrypt and decrypt using the Raw RSA Keyring example. + + Here user provides the public and private keys. To test this, we create the + keys using the generate_rsa_keys function and write them to the file. + Then we call the encrypt_and_decrypt_with_keyring function and pass them + """ + # Generate the user keys for testing + user_public_key, user_private_key = generate_rsa_keys() + + # Convert the keys to strings + user_public_key = user_public_key.decode('utf-8') + user_private_key = user_private_key.decode('utf-8') + + test_keys_directory = 'test_keys' + if not os.path.exists(test_keys_directory): + os.makedirs(test_keys_directory) + + # Define the file names for the keys + user_public_key_file_name = test_keys_directory + '/user_public_key_file_name.pem' + user_private_key_file_name = test_keys_directory + '/user_private_key_file_name.pem' + + # Write the public key to the file + with open(user_public_key_file_name, "w", encoding="utf-8") as f: + f.write(user_public_key) + + # Write the private key to the file + with open(user_private_key_file_name, "w", encoding="utf-8") as f: + f.write(user_private_key) + + encrypt_and_decrypt_with_keyring(public_key_file_name=user_public_key_file_name, + private_key_file_name=user_private_key_file_name) + + +def test_encrypt_and_decrypt_fails_if_user_provides_only_public_key(): + """Test function for encrypt and decrypt using the Raw RSA Keyring example. + + Here user provides only the public key. The program should throw an Value error + as this example requires the user to either provide both private and public keys to + test both encryption and decryption, or not provide any keys and the example generates both + """ + # Generate the user keys for testing + user_public_key, user_private_key = generate_rsa_keys() + + # Convert the public key to string + user_public_key = user_public_key.decode('utf-8') + + test_keys_directory = 'test_keys' + if not os.path.exists(test_keys_directory): + os.makedirs(test_keys_directory) + + # Define the file name for the public key + user_public_key_file_name = test_keys_directory + '/user_public_key_file_name.pem' + + # Write the public key to the file + with open(user_public_key_file_name, "w", encoding="utf-8") as f: + f.write(user_public_key) + + try: + encrypt_and_decrypt_with_keyring(public_key_file_name=user_public_key_file_name) + + raise AssertionError("encrypt_and_decrypt_with_keyring should raise an error") + except ValueError: + pass + + +def test_encrypt_and_decrypt_fails_if_user_provides_only_private_key(): + """Test function for encrypt and decrypt using the Raw RSA Keyring example. + + Here user provides only the private key. The program should throw an Value error + as this example requires the user to either provide both private and public keys to + test both encryption and decryption, or not provide any keys and the example generates both + """ + # Generate the user keys for testing + user_public_key, user_private_key = generate_rsa_keys() + + # Convert the private key to string + user_private_key = user_private_key.decode('utf-8') + + test_keys_directory = 'test_keys' + if not os.path.exists(test_keys_directory): + os.makedirs(test_keys_directory) + + # Define the file name for the private key + user_private_key_file_name = test_keys_directory + '/user_private_key_file_name.pem' + + # Write the private key to the file + with open(user_private_key_file_name, "w", encoding="utf-8") as f: + f.write(user_private_key) + + try: + encrypt_and_decrypt_with_keyring(private_key_file_name=user_private_key_file_name) + + raise AssertionError("encrypt_and_decrypt_with_keyring should raise an error") + except ValueError: + pass diff --git a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py index 1f2102757..d0e58661d 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py @@ -7,7 +7,10 @@ # pylint should pass even if the MPL isn't installed # Also thinks these imports aren't used if it can't import them # noqa pylint: disable=import-error,unused-import -from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException +from aws_cryptographic_materialproviders.mpl.errors import ( + AwsCryptographicMaterialProvidersException, + CollectionOfErrors, +) from aws_cryptographic_materialproviders.mpl.models import ( AlgorithmSuiteIdESDK as MPL_AlgorithmSuiteIdESDK, CommitmentPolicyESDK as MPL_CommitmentPolicyESDK, @@ -114,7 +117,7 @@ def decrypt_materials( CryptoMaterialsManagerFromMPL._create_mpl_decrypt_materials_input_from_request(request) mpl_output: 'MPL_DecryptMaterialsOutput' = self.mpl_cmm.decrypt_materials(mpl_input) return DecryptionMaterialsFromMPL(mpl_output.decryption_materials) - except AwsCryptographicMaterialProvidersException as mpl_exception: + except (AwsCryptographicMaterialProvidersException, CollectionOfErrors) as mpl_exception: # Wrap MPL error into the ESDK error type # so customers only have to catch ESDK error types. raise AWSEncryptionSDKClientError(mpl_exception) From 428fe95e84ab9c9a8245ca21801366a911196149 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Thu, 2 May 2024 17:19:03 -0700 Subject: [PATCH 06/51] chore: added keyring examples (kms_rsa, multi, discovery) (#671) --- .../aws_kms_discovery_keyring_example.py | 206 +++++++++++++++++ ...aws_kms_discovery_multi_keyring_example.py | 173 +++++++++++++++ .../keyrings/aws_kms_multi_keyring_example.py | 204 +++++++++++++++++ .../keyrings/aws_kms_rsa_keyring_example.py | 125 +++++++++++ examples/src/keyrings/hierarchical_keyring.py | 2 +- .../src/keyrings/multi_keyring_example.py | 209 ++++++++++++++++++ ...est_i_aws_kms_discovery_keyring_example.py | 16 ++ ...aws_kms_discovery_multi_keyring_example.py | 16 ++ .../test_i_aws_kms_multi_keyring_example.py | 22 ++ .../test_i_aws_kms_rsa_keyring_example.py | 25 +++ .../keyrings/test_i_multi_keyring_example.py | 14 ++ .../materials_managers/mpl/cmm.py | 28 ++- .../unit/test_material_managers_mpl_cmm.py | 50 +++-- 13 files changed, 1060 insertions(+), 30 deletions(-) create mode 100644 examples/src/keyrings/aws_kms_discovery_keyring_example.py create mode 100644 examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py create mode 100644 examples/src/keyrings/aws_kms_multi_keyring_example.py create mode 100644 examples/src/keyrings/aws_kms_rsa_keyring_example.py create mode 100644 examples/src/keyrings/multi_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py create mode 100644 examples/test/keyrings/test_i_multi_keyring_example.py diff --git a/examples/src/keyrings/aws_kms_discovery_keyring_example.py b/examples/src/keyrings/aws_kms_discovery_keyring_example.py new file mode 100644 index 000000000..24dc111f1 --- /dev/null +++ b/examples/src/keyrings/aws_kms_discovery_keyring_example.py @@ -0,0 +1,206 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS Discovery Keyring + +AWS KMS discovery keyring is an AWS KMS keyring that doesn't specify any wrapping keys. + +The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring +for AWS KMS multi-Region keys. For information about using multi-Region keys with the +AWS Encryption SDK, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks + +Because it doesn't specify any wrapping keys, a discovery keyring can't encrypt data. +If you use a discovery keyring to encrypt data, alone or in a multi-keyring, the encrypt +operation fails. + +When decrypting, a discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt +any encrypted data key by using the AWS KMS key that encrypted it, regardless of who owns or +has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt +permission on the AWS KMS key. + +This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This encrypted ciphertext is then decrypted using the Discovery keyring. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +4. Decryption is only possible if the Discovery Keyring contains the correct AWS Account ID's to + which the KMS key used for encryption belongs +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on how to use KMS Discovery keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsDiscoveryKeyringInput, + CreateAwsKmsKeyringInput, + DiscoveryFilter, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str, + aws_account_id: str, + aws_region: str +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Keyring. + + Usage: encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for creating + the kms_keyring used for encryption + :type kms_key_id: string + :param aws_account_id: AWS Account ID to use in the discovery filter + :type aws_account_id: string + :param aws_region: AWS Region to use for the kms client + :type aws_region: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Create the keyring that determines how your data keys are protected. + # Although this example highlights Discovery keyrings, Discovery keyrings cannot + # be used to encrypt, so for encryption we create a KMS keyring without discovery mode. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + encrypt_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=kms_keyring_input + ) + + # 5. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=encrypt_kms_keyring, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Now create a Discovery keyring to use for decryption. We'll add a discovery filter + # so that we limit the set of ciphertexts we are willing to decrypt to only ones + # created by KMS keys in our account and partition. + + discovery_keyring_input: CreateAwsKmsDiscoveryKeyringInput = CreateAwsKmsDiscoveryKeyringInput( + kms_client=kms_client, + discovery_filter=DiscoveryFilter( + account_ids=[aws_account_id], + partition="aws" + ) + ) + + discovery_keyring: IKeyring = mat_prov.create_aws_kms_discovery_keyring( + input=discovery_keyring_input + ) + + # 8. Decrypt your encrypted data using the discovery keyring. + # On Decrypt, the header of the encrypted message (ciphertext) will be parsed. + # The header contains the Encrypted Data Keys (EDKs), which, if the EDK + # was encrypted by a KMS Keyring, includes the KMS Key ARN. + # The Discovery Keyring filters these EDKs for + # EDKs encrypted by Single Region OR Multi Region KMS Keys. + # If a Discovery Filter is present, these KMS Keys must belong + # to an AWS Account ID in the discovery filter's AccountIds and + # must be from the discovery filter's partition. + # Finally, KMS is called to decrypt each filtered EDK until an EDK is + # successfully decrypted. The resulting data key is used to decrypt the + # ciphertext's message. + # If all calls to KMS fail, the decryption fails. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=discovery_keyring + ) + + # 9. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA + + # 11. Demonstrate that if a discovery keyring (Bob's) doesn't have the correct AWS Account ID's, + # the decrypt will fail with an error message + # Note that this assumes Account ID used here ('888888888888') is different than the one used + # during encryption + discovery_keyring_input_bob: CreateAwsKmsDiscoveryKeyringInput = \ + CreateAwsKmsDiscoveryKeyringInput( + kms_client=kms_client, + discovery_filter=DiscoveryFilter( + account_ids=["888888888888"], + partition="aws" + ) + ) + + discovery_keyring_bob: IKeyring = mat_prov.create_aws_kms_discovery_keyring( + input=discovery_keyring_input_bob + ) + + # Decrypt the ciphertext using Bob's discovery keyring which doesn't contain the required + # Account ID's for the KMS keyring used for encryption. + # This should throw an AWSEncryptionSDKClientError exception + try: + plaintext_bytes, _ = client.decrypt( + source=ciphertext, + keyring=discovery_keyring_bob + ) + + raise AssertionError("Decrypt using discovery keyring with wrong AWS Account ID should" + + "raise AWSEncryptionSDKClientError") + except AWSEncryptionSDKClientError: + pass diff --git a/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py b/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py new file mode 100644 index 000000000..0830ecb58 --- /dev/null +++ b/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py @@ -0,0 +1,173 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS Discovery Multi Keyring and demonstrates decryption +using a Multi-Keyring containing multiple AWS KMS Discovery Keyrings. + +The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring +for AWS KMS multi-Region keys. For information about using multi-Region keys with the +AWS Encryption SDK, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks + +Because it doesn't specify any wrapping keys, a discovery keyring can't encrypt data. +If you use a discovery keyring to encrypt data, alone or in a multi-keyring, the encrypt +operation fails. + +When decrypting, a discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt +any encrypted data key by using the AWS KMS key that encrypted it, regardless of who owns or +has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt +permission on the AWS KMS key. + +This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This encrypted ciphertext is then decrypted using the Discovery Multi +keyring. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on how to use KMS Discovery keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsDiscoveryMultiKeyringInput, + CreateAwsKmsKeyringInput, + DiscoveryFilter, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str, + aws_account_id: str, + aws_regions: list[str] +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Multi Keyring. + + Usage: encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_id, aws_regions) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for creating + the kms_keyring used for encryption + :type kms_key_id: string + :param aws_account_id: AWS Account ID to use in the discovery filter + :type aws_account_id: string + :param aws_regions: List of AWS Regions to use for creating the discovery multi keyring + :type aws_regions: list[string] + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Create the keyring that determines how your data keys are protected. + # Although this example highlights Discovery keyrings, Discovery keyrings cannot + # be used to encrypt, so for encryption we create a KMS keyring without discovery mode. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + encrypt_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=kms_keyring_input + ) + + # 5. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=encrypt_kms_keyring, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Now create a Discovery Multi keyring to use for decryption. We'll add a discovery filter + # so that we limit the set of ciphertexts we are willing to decrypt to only ones + # created by KMS keys in our account and partition. + discovery_multi_keyring_input: CreateAwsKmsDiscoveryMultiKeyringInput = \ + CreateAwsKmsDiscoveryMultiKeyringInput( + regions=aws_regions, + discovery_filter=DiscoveryFilter( + account_ids=[aws_account_id], + partition="aws" + ) + ) + + # This is a Multi Keyring composed of Discovery Keyrings. + # There is a keyring for every region in `regions`. + # All the keyrings have the same Discovery Filter. + # Each keyring has its own KMS Client, which is created for the keyring's region. + discovery_multi_keyring: IKeyring = mat_prov.create_aws_kms_discovery_multi_keyring( + input=discovery_multi_keyring_input + ) + + # 8. On Decrypt, the header of the encrypted message (ciphertext) will be parsed. + # The header contains the Encrypted Data Keys (EDKs), which, if the EDK + # was encrypted by a KMS Keyring, includes the KMS Key ARN. + # For each member of the Multi Keyring, every EDK will try to be decrypted until a decryption + # is successful. + # Since every member of the Multi Keyring is a Discovery Keyring: + # Each Keyring will filter the EDKs by the Discovery Filter + # For the filtered EDKs, the keyring will try to decrypt it with the keyring's client. + # All of this is done serially, until a success occurs or all keyrings have + # failed all (filtered) EDKs. + # KMS Discovery Keyrings will attempt to decrypt Multi Region Keys (MRKs) and regular KMS Keys. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=discovery_multi_keyring + ) + + # 9. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/aws_kms_multi_keyring_example.py b/examples/src/keyrings/aws_kms_multi_keyring_example.py new file mode 100644 index 000000000..0e556f5e3 --- /dev/null +++ b/examples/src/keyrings/aws_kms_multi_keyring_example.py @@ -0,0 +1,204 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS Multi Keyring made up of multiple AWS KMS Keyrings. + +A multi-keyring is a keyring that consists of one or more individual keyrings of the +same or a different type. The effect is like using several keyrings in a series. +When you use a multi-keyring to encrypt data, any of the wrapping keys in any of its +keyrings can decrypt that data. + +When you create a multi-keyring to encrypt data, you designate one of the keyrings as +the generator keyring. All other keyrings are known as child keyrings. The generator keyring +generates and encrypts the plaintext data key. Then, all of the wrapping keys in all of the +child keyrings encrypt the same plaintext data key. The multi-keyring returns the plaintext +key and one encrypted data key for each wrapping key in the multi-keyring. If you create a +multi-keyring with no generator keyring, you can use it to decrypt data, but not to encrypt. +If the generator keyring is a KMS keyring, the generator key in the AWS KMS keyring generates +and encrypts the plaintext key. Then, all additional AWS KMS keys in the AWS KMS keyring, +and all wrapping keys in all child keyrings in the multi-keyring, encrypt the same plaintext key. + +When decrypting, the AWS Encryption SDK uses the keyrings to try to decrypt one of the encrypted +data keys. The keyrings are called in the order that they are specified in the multi-keyring. +Processing stops as soon as any key in any keyring can decrypt an encrypted data key. + +This example creates a Multi Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Decryption of ciphertext is possible using the multi_keyring, + and every one of the keyrings from the multi_keyring separately +3. All decrypted plaintext value match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +This example creates a multi_keyring using a KMS keyring as generator keyring and +another KMS keyring as a child keyring. + +For more information on how to use Multi keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput, CreateAwsKmsMultiKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + default_region_kms_key_id: str, + second_region_kms_key_id: str, + default_region: str, + second_region: str +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS Multi keyring. + The multi_keyring is created using a KMS keyring as generator keyring and another KMS keyring + as a child keyring. For this example, `default_region_kms_key_id` is the generator key id + for a KMS key located in your default region, and `second_region_kms_key_id` is the KMS key id + for a KMS Key located in some second region. + + Usage: encrypt_and_decrypt_with_keyring(default_region_kms_key_id, + second_region_kms_key_id, + default_region, + second_region) + :param default_region_kms_key_id: KMS Key identifier for the default region KMS key you want to + use as a generator keyring + :type default_region_kms_key_id: string + :param second_region_kms_key_id: KMS Key identifier for the second region KMS key you want to + use as a child keyring + :type second_region_kms_key_id: string + :param default_region: AWS Region for the default region KMS key + :type default_region: string + :param second_region: AWS Region for the second region KMS key + :type second_region: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create an AwsKmsMultiKeyring that protects your data under two different KMS Keys. + # Either KMS Key individually is capable of decrypting data encrypted under this Multi Keyring. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput( + generator=default_region_kms_key_id, + kms_key_ids=[second_region_kms_key_id] + ) + + kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring( + input=kms_multi_keyring_input + ) + + # 4. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=kms_multi_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6a. Decrypt your encrypted data using the same multi_keyring you used on encrypt. + plaintext_bytes_multi_keyring, _ = client.decrypt( + source=ciphertext, + keyring=kms_multi_keyring + ) + + # 6b. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_multi_keyring == EXAMPLE_DATA + + # Because you used a multi_keyring on Encrypt, you can use either of the two + # kms keyrings individually to decrypt the data. + + # 7. Demonstrate that you can successfully decrypt data using a KMS keyring with just the + # `default_region_kms_key_id` directly. + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 7a. Create a boto3 client for KMS for the default region. + default_region_kms_client = boto3.client('kms', region_name=default_region) + + # 7b. Create KMS keyring + default_region_kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=default_region_kms_key_id, + kms_client=default_region_kms_client + ) + + default_region_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=default_region_kms_keyring_input + ) + + # 7c. Decrypt your encrypted data using the default_region_kms_keyring. + plaintext_bytes_default_region_kms_keyring, _ = client.decrypt( + source=ciphertext, + keyring=default_region_kms_keyring + ) + + # 7d. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_default_region_kms_keyring == EXAMPLE_DATA + + # 8. Demonstrate that you can also successfully decrypt data using a KMS keyring with just the + # `second_region_kms_key_id` directly. + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 8a. Create a boto3 client for KMS for the second region. + second_region_kms_client = boto3.client('kms', region_name=second_region) + + # 8b. Create KMS keyring + second_region_kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=second_region_kms_key_id, + kms_client=second_region_kms_client + ) + + second_region_kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=second_region_kms_keyring_input + ) + + # 8c. Decrypt your encrypted data using the second_region_kms_keyring. + plaintext_bytes_second_region_kms_keyring, _ = client.decrypt( + source=ciphertext, + keyring=second_region_kms_keyring + ) + + # 8d. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_second_region_kms_keyring == EXAMPLE_DATA diff --git a/examples/src/keyrings/aws_kms_rsa_keyring_example.py b/examples/src/keyrings/aws_kms_rsa_keyring_example.py new file mode 100644 index 000000000..5c0bbe736 --- /dev/null +++ b/examples/src/keyrings/aws_kms_rsa_keyring_example.py @@ -0,0 +1,125 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS RSA Keyring + +This example creates a KMS RSA Keyring and then encrypts a custom input +EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for +demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +# For more information on how to use KMS keyrings, see +# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsRsaKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.identifiers import AlgorithmSuite + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_rsa_key_id: str, + public_key: str +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS RSA keyring. + + Usage: encrypt_and_decrypt_with_keyring(kms_rsa_key_id, public_key) + :param kms_rsa_key_id: KMS RSA Key identifier for the KMS RSA key you want to use + :type kms_rsa_key_id: string + :param public_key: public key you want to use + :type public_key: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Create a KMS RSA keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create the AWS KMS RSA keyring input + # For more information on the allowed encryption algorithms, please see + # https://docs.aws.amazon.com/kms/latest/developerguide/asymmetric-key-specs.html#key-spec-rsa + keyring_input: CreateAwsKmsRsaKeyringInput = CreateAwsKmsRsaKeyringInput( + public_key=public_key, + kms_key_id=kms_rsa_key_id, + encryption_algorithm="RSAES_OAEP_SHA_256", + kms_client=kms_client + ) + + kms_rsa_keyring: IKeyring = mat_prov.create_aws_kms_rsa_keyring( + input=keyring_input + ) + + # 5. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=kms_rsa_keyring, + encryption_context=encryption_context, + algorithm=AlgorithmSuite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=kms_rsa_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/hierarchical_keyring.py b/examples/src/keyrings/hierarchical_keyring.py index 32a6cbf8b..5642a0b71 100644 --- a/examples/src/keyrings/hierarchical_keyring.py +++ b/examples/src/keyrings/hierarchical_keyring.py @@ -154,7 +154,7 @@ def encrypt_and_decrypt_with_keyring( "the data you are handling": "is what you think it is", } - # 8. Encrypt the data for encryptionContextA & encryptionContextB + # 8. Encrypt the data with encryptionContextA & encryptionContextB ciphertext_A, _ = client.encrypt( source=EXAMPLE_DATA, keyring=hierarchical_keyring, diff --git a/examples/src/keyrings/multi_keyring_example.py b/examples/src/keyrings/multi_keyring_example.py new file mode 100644 index 000000000..58e4839ac --- /dev/null +++ b/examples/src/keyrings/multi_keyring_example.py @@ -0,0 +1,209 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the Multi Keyring + +A multi-keyring is a keyring that consists of one or more individual keyrings of the +same or a different type. The effect is like using several keyrings in a series. +When you use a multi-keyring to encrypt data, any of the wrapping keys in any of its +keyrings can decrypt that data. + +When you create a multi-keyring to encrypt data, you designate one of the keyrings as +the generator keyring. All other keyrings are known as child keyrings. The generator keyring +generates and encrypts the plaintext data key. Then, all of the wrapping keys in all of the +child keyrings encrypt the same plaintext data key. The multi-keyring returns the plaintext +key and one encrypted data key for each wrapping key in the multi-keyring. If you create a +multi-keyring with no generator keyring, you can use it to decrypt data, but not to encrypt. +If the generator keyring is a KMS keyring, the generator key in the AWS KMS keyring generates +and encrypts the plaintext key. Then, all additional AWS KMS keys in the AWS KMS keyring, +and all wrapping keys in all child keyrings in the multi-keyring, encrypt the same plaintext key. + +When decrypting, the AWS Encryption SDK uses the keyrings to try to decrypt one of the encrypted +data keys. The keyrings are called in the order that they are specified in the multi-keyring. +Processing stops as soon as any key in any keyring can decrypt an encrypted data key. + +This example creates a Multi Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Decryption of ciphertext is possible using the multi_keyring, +and every one of the keyrings from the multi_keyring separately +3. All decrypted plaintext value match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +This example creates a multi_keyring using a KMS keyring as generator keyring and a raw AES keyring +as a child keyring. You can use different combinations of keyrings in the multi_keyring. + +For more information on how to use Multi keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html +""" +import secrets +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + AesWrappingAlg, + CreateAwsKmsKeyringInput, + CreateMultiKeyringInput, + CreateRawAesKeyringInput, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str +): + """Demonstrate an encrypt/decrypt cycle using a Multi keyring. + The multi_keyring is created using a KMS keyring as generator keyring and a raw AES keyring + as a child keyring. Therefore, we take a kms_key_id as input + + Usage: encrypt_and_decrypt_with_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys in the kms_keyring, that is in-turn used in the multi_keyring + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Initialize the material providers library + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # 5. Create a KMS keyring + kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=kms_keyring_input + ) + + # 6. Create a raw AES keyring to additionally encrypt under as child_keyring + + # The key namespace and key name are defined by you. + # and are used by the Raw AES keyring to determine + # whether it should attempt to decrypt an encrypted data key. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # Generate a 256-bit AES key to use with your raw AES keyring. + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + static_key = secrets.token_bytes(32) + + raw_aes_keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=raw_aes_keyring_input + ) + + # 7. Create a multi_keyring that consists of the previously created keyrings. + # When using this multi_keyring to encrypt data, either `kms_keyring` or + # `raw_aes_keyring` (or a multi_keyring containing either) may be used to decrypt the data. + multi_keyring_input: CreateMultiKeyringInput = CreateMultiKeyringInput( + generator=kms_keyring, + child_keyrings=[raw_aes_keyring] + ) + + multi_keyring: IKeyring = mat_prov.create_multi_keyring( + input=multi_keyring_input + ) + + # 8. Encrypt the data with the encryptionContext + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=multi_keyring, + encryption_context=encryption_context + ) + + # 9. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 10a. Decrypt your encrypted data using the same multi_keyring you used on encrypt. + plaintext_bytes_multi_keyring, _ = client.decrypt( + source=ciphertext, + keyring=multi_keyring + ) + + # 10b. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_multi_keyring == EXAMPLE_DATA + + # Because you used a multi_keyring on Encrypt, you can use either the + # `kms_keyring` or `raw_aes_keyring` individually to decrypt the data. + + # 11. Demonstrate that you can successfully decrypt data using just the `kms_keyring` + # directly. + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 11a. Decrypt your encrypted data using the kms_keyring. + plaintext_bytes_kms_keyring, _ = client.decrypt( + source=ciphertext, + keyring=kms_keyring + ) + + # 11b. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_kms_keyring == EXAMPLE_DATA + + # 12. Demonstrate that you can also successfully decrypt data using the `raw_aes_keyring` + # directly. + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 12a. Decrypt your encrypted data using the raw_aes_keyring. + plaintext_bytes_raw_aes_keyring, _ = client.decrypt( + source=ciphertext, + keyring=raw_aes_keyring + ) + + # 12b. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_raw_aes_keyring == EXAMPLE_DATA diff --git a/examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py new file mode 100644 index 000000000..af3c2a3a3 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS Discovery keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_discovery_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS Discovery Keyring example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + aws_account_id = "658956600833" + aws_region = "us-west-2" + encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_id, aws_region) diff --git a/examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py new file mode 100644 index 000000000..eff2a1a3b --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS Discovery Multi keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS Discovery Multi Keyring example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + aws_account_id = "658956600833" + aws_regions = ["us-east-1", "us-west-2"] + encrypt_and_decrypt_with_keyring(kms_key_id, aws_account_id, aws_regions) diff --git a/examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py new file mode 100644 index 000000000..10f991754 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py @@ -0,0 +1,22 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS multi keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_multi_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS Multi Keyring example.""" + default_region_kms_key_id = \ + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + second_region_kms_key_id = \ + "arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2" + default_region = "us-west-2" + second_region = "eu-central-1" + encrypt_and_decrypt_with_keyring(default_region_kms_key_id, + second_region_kms_key_id, + default_region, + second_region) diff --git a/examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py new file mode 100644 index 000000000..4d953947a --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py @@ -0,0 +1,25 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS RSA keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_rsa_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS RSA Keyring example.""" + kms_rsa_key_id = "arn:aws:kms:us-west-2:370957321024:key/mrk-63d386cb70614ea59b32ad65c9315297" + + # THIS IS A PUBLIC RESOURCE AND SHOULD NOT BE USED IN A PRODUCTION ENVIRONMENT + public_key = bytes("-----BEGIN PUBLIC KEY-----\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA27Uc/fBaMVhxCE/SpCMQ" + + "oSBRSzQJw+o2hBaA+FiPGtiJ/aPy7sn18aCkelaSj4kwoC79b/arNHlkjc7OJFsN" + + "/GoFKgNvaiY4lOeJqEiWQGSSgHtsJLdbO2u4OOSxh8qIRAMKbMgQDVX4FR/PLKeK" + + "fc2aCDvcNSpAM++8NlNmv7+xQBJydr5ce91eISbHkFRkK3/bAM+1iddupoRw4Wo2" + + "r3avzrg5xBHmzR7u1FTab22Op3Hgb2dBLZH43wNKAceVwKqKA8UNAxashFON7xK9" + + "yy4kfOL0Z/nhxRKe4jRZ/5v508qIzgzCksYy7Y3QbMejAtiYnr7s5/d5KWw0swou" + + "twIDAQAB" + + "\n-----END PUBLIC KEY-----", 'utf-8') + encrypt_and_decrypt_with_keyring(kms_rsa_key_id, public_key) diff --git a/examples/test/keyrings/test_i_multi_keyring_example.py b/examples/test/keyrings/test_i_multi_keyring_example.py new file mode 100644 index 000000000..ad12c0c9c --- /dev/null +++ b/examples/test/keyrings/test_i_multi_keyring_example.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the multi keyring example.""" +import pytest + +from ...src.keyrings.multi_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the Multi Keyring example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_keyring(kms_key_id) diff --git a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py index d0e58661d..49a743f89 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py @@ -81,18 +81,24 @@ def get_encryption_materials( def _native_to_mpl_get_encryption_materials( request: EncryptionMaterialsRequest ) -> 'MPL_GetEncryptionMaterialsInput': - commitment_policy = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy( - request.commitment_policy - ) - output: MPL_GetEncryptionMaterialsInput = MPL_GetEncryptionMaterialsInput( - encryption_context=request.encryption_context, - commitment_policy=commitment_policy, - max_plaintext_length=request.plaintext_length, - ) - return output + output_kwargs = { + "encryption_context": request.encryption_context, + "max_plaintext_length": request.plaintext_length, + "commitment_policy": CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy( + request.commitment_policy + ) + } + + if request.algorithm is not None: + output_kwargs["algorithm_suite_id"] = \ + CryptoMaterialsManagerFromMPL._native_algorithm_id_to_mpl_algorithm_id( + request.algorithm.algorithm_id + ) + + return MPL_GetEncryptionMaterialsInput(**output_kwargs) @staticmethod - def _native_to_mpl_commmitment_policy( + def _native_to_mpl_commitment_policy( native_commitment_policy: CommitmentPolicy ) -> 'MPL_CommitmentPolicyESDK': if native_commitment_policy == CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT: @@ -141,7 +147,7 @@ def _create_mpl_decrypt_materials_input_from_request( algorithm_suite_id=CryptoMaterialsManagerFromMPL._native_algorithm_id_to_mpl_algorithm_id( request.algorithm.algorithm_id ), - commitment_policy=CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy( + commitment_policy=CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy( request.commitment_policy ), encrypted_data_keys=list_edks, diff --git a/test/mpl/unit/test_material_managers_mpl_cmm.py b/test/mpl/unit/test_material_managers_mpl_cmm.py index 0551e8f30..603446550 100644 --- a/test/mpl/unit/test_material_managers_mpl_cmm.py +++ b/test/mpl/unit/test_material_managers_mpl_cmm.py @@ -97,10 +97,17 @@ def test_GIVEN_valid_request_WHEN_get_encryption_materials_THEN_return_Encryptio @patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" - "._native_to_mpl_commmitment_policy") + "._native_algorithm_id_to_mpl_algorithm_id") +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_commitment_policy") def test_GIVEN_mpl_cmm_raises_MPLException_WHEN_get_encryption_materials_THEN_raise_ESDKException( - _ + _, + mock_mpl_algorithm_id, ): + # Given: _native_algorithm_id_to_mpl_algorithm_id returns a valid MPL algorithm ID + mock_algorithm_id = "0x1234" # Some fake algorithm ID that fits the format + mock_mpl_algorithm_id.return_value = mock_algorithm_id + # Then: Raises AWSEncryptionSDKClientError with pytest.raises(AWSEncryptionSDKClientError): # Given: mpl_cmm.get_encryption_materials raises MPL exception @@ -112,10 +119,17 @@ def test_GIVEN_mpl_cmm_raises_MPLException_WHEN_get_encryption_materials_THEN_ra @patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" - "._native_to_mpl_commmitment_policy") + "._native_algorithm_id_to_mpl_algorithm_id") +@patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" + "._native_to_mpl_commitment_policy") def test_GIVEN_valid_mpl_commitment_policy_WHEN_native_to_mpl_get_encryption_materials_THEN_returns_MPL_GetEncryptionMaterialsInput( # noqa: E501 - mock_mpl_commitment_policy + mock_mpl_commitment_policy, + mock_mpl_algorithm_id, ): + # Given: _native_algorithm_id_to_mpl_algorithm_id returns a valid MPL algorithm ID + mock_algorithm_id = "0x1234" # Some fake algorithm ID that fits the format + mock_mpl_algorithm_id.return_value = mock_algorithm_id + # Given: commitment policy is some MPL ESDK commitment policy mock_commitment_policy = MagicMock(__class__=MPL_CommitmentPolicyESDK) mock_mpl_commitment_policy.return_value = mock_commitment_policy @@ -132,50 +146,50 @@ def test_GIVEN_valid_mpl_commitment_policy_WHEN_native_to_mpl_get_encryption_mat assert output.max_plaintext_length == mock_encryption_materials_request.plaintext_length -def test_GIVEN_CommitmentPolicy_FORBID_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_FORBID_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 +def test_GIVEN_CommitmentPolicy_FORBID_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_FORBID_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 # Given: native FORBID_ENCRYPT_ALLOW_DECRYPT native_commitment_policy = CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT - # When: _native_to_mpl_commmitment_policy - output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + # When: _native_to_mpl_commitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy(native_commitment_policy) # Then: Returns MPL FORBID_ENCRYPT_ALLOW_DECRYPT assert isinstance(output, MPL_CommitmentPolicyESDK) assert output.value == "FORBID_ENCRYPT_ALLOW_DECRYPT" -def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 +def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_ALLOW_DECRYPT_WHEN_native_to_mpl_commitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_ALLOW_DECRYPT(): # noqa: E501 # Given: native REQUIRE_ENCRYPT_ALLOW_DECRYPT native_commitment_policy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT - # When: _native_to_mpl_commmitment_policy - output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + # When: _native_to_mpl_commitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy(native_commitment_policy) # Then: Returns MPL REQUIRE_ENCRYPT_ALLOW_DECRYPT assert isinstance(output, MPL_CommitmentPolicyESDK) assert output.value == "REQUIRE_ENCRYPT_ALLOW_DECRYPT" -def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_REQUIRE_DECRYPT_WHEN_native_to_mpl_commmitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_REQUIRE_DECRYPT(): # noqa: E501 +def test_GIVEN_CommitmentPolicy_REQUIRE_ENCRYPT_REQUIRE_DECRYPT_WHEN_native_to_mpl_commitment_policy_THEN_returns_MPL_CommitmentPolicyESDK_REQUIRE_ENCRYPT_REQUIRE_DECRYPT(): # noqa: E501 # Given: native REQUIRE_ENCRYPT_REQUIRE_DECRYPT native_commitment_policy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT - # When: _native_to_mpl_commmitment_policy - output = CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + # When: _native_to_mpl_commitment_policy + output = CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy(native_commitment_policy) # Then: Returns MPL REQUIRE_ENCRYPT_REQUIRE_DECRYPT assert isinstance(output, MPL_CommitmentPolicyESDK) assert output.value == "REQUIRE_ENCRYPT_REQUIRE_DECRYPT" -def test_GIVEN_CommitmentPolicy_unrecognized_WHEN_native_to_mpl_commmitment_policy_THEN_raise_ValueError(): +def test_GIVEN_CommitmentPolicy_unrecognized_WHEN_native_to_mpl_commitment_policy_THEN_raise_ValueError(): # Given: invalid native commitment policy native_commitment_policy = "not a commitment policy" # Then: Raises ValueError with pytest.raises(ValueError): - # When: _native_to_mpl_commmitment_policy - CryptoMaterialsManagerFromMPL._native_to_mpl_commmitment_policy(native_commitment_policy) + # When: _native_to_mpl_commitment_policy + CryptoMaterialsManagerFromMPL._native_to_mpl_commitment_policy(native_commitment_policy) @patch.object(mock_mpl_cmm, "decrypt_materials") @@ -239,7 +253,7 @@ def test_GIVEN_valid_native_algorithm_id_WHEN_native_algorithm_id_to_mpl_algorit @patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" "._native_algorithm_id_to_mpl_algorithm_id") @patch("aws_encryption_sdk.materials_managers.mpl.cmm.CryptoMaterialsManagerFromMPL" - "._native_to_mpl_commmitment_policy") + "._native_to_mpl_commitment_policy") def test_GIVEN_valid_request_WHEN_create_mpl_decrypt_materials_input_from_request_THEN_returns_MPL_MPL_DecryptMaterialsInput( # noqa: E501 mock_mpl_commitment_policy, mock_mpl_algorithm_id, @@ -248,7 +262,7 @@ def test_GIVEN_valid_request_WHEN_create_mpl_decrypt_materials_input_from_reques mock_algorithm_id = "0x1234" # Some fake algorithm ID that fits the format mock_mpl_algorithm_id.return_value = mock_algorithm_id - # Given: _native_to_mpl_commmitment_policy returns some MPL commitment policy + # Given: _native_to_mpl_commitment_policy returns some MPL commitment policy mock_commitment_policy = MagicMock(__class__=MPL_CommitmentPolicyESDK) mock_mpl_commitment_policy.return_value = mock_commitment_policy From 52ad465ccb145977835163091c535754090c6459 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Fri, 3 May 2024 13:14:58 -0700 Subject: [PATCH 07/51] chore(examples): Added mrk and mrk_multi keyring examples (#673) --- .../keyrings/aws_kms_mrk_keyring_example.py | 154 +++++++++++++++ .../aws_kms_mrk_multi_keyring_example.py | 183 ++++++++++++++++++ .../test_i_aws_kms_mrk_keyring_example.py | 22 +++ ...est_i_aws_kms_mrk_multi_keyring_example.py | 23 +++ 4 files changed, 382 insertions(+) create mode 100644 examples/src/keyrings/aws_kms_mrk_keyring_example.py create mode 100644 examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py diff --git a/examples/src/keyrings/aws_kms_mrk_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_keyring_example.py new file mode 100644 index 000000000..b82748cf9 --- /dev/null +++ b/examples/src/keyrings/aws_kms_mrk_keyring_example.py @@ -0,0 +1,154 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS MRK (multi-region key) Keyring + +The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to +create, encrypt, and decrypt data keys with multi-region AWS KMS keys (MRKs). +This example creates a KMS MRK Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +AWS KMS MRK keyrings can be used independently or in a multi-keyring with other keyrings +of the same or a different type. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html + +For more info on KMS MRK (multi-region keys), see the KMS documentation: +https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + mrk_key_id_encrypt: str, + mrk_replica_key_id_decrypt: str, + mrk_encrypt_region: str, + mrk_replica_decrypt_region: str +): + """Demonstrate an encrypt/decrypt cycle using an AWS KMS MRK keyring. + + Usage: encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + mrk_replica_key_id_decrypt, + mrk_encrypt_region, + mrk_replica_decrypt_region) + :param mrk_key_id_encrypt: KMS Key identifier for the KMS key located in your + default region, which you want to use for encryption of your data keys + :type mrk_key_id_encrypt: string + :param mrk_replica_key_id_decrypt: KMS Key identifier for the KMS key + that is a replica of the `mrk_key_id_encrypt` in a second region, which you + want to use for decryption of your data keys + :type mrk_replica_key_id_decrypt: string + :param mrk_encrypt_region: AWS Region for encryption of your data keys. This should + be the region of the mrk_key_id_encrypt. + :type mrk_encrypt_region: string + :param mrk_replica_decrypt_region: AWS Region for decryption of your data keys. This should + be the region of the mrk_replica_key_id_decrypt. + :type mrk_replica_decrypt_region: string + + For more information on KMS Key identifiers for multi-region keys, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create a keyring that will encrypt your data, using a KMS MRK in the first region. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create a boto3 client for KMS in the first region. + encrypt_kms_client = boto3.client('kms', region_name=mrk_encrypt_region) + + encrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( + kms_key_id=mrk_key_id_encrypt, + kms_client=encrypt_kms_client + ) + + encrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( + input=encrypt_keyring_input + ) + + # 4. Encrypt the data with the encryptionContext using the encrypt_keyring. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=encrypt_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6. Create a keyring that will decrypt your data, using the same KMS MRK replicated + # to the second region. This example assumes you have already replicated your key + + # Create a boto3 client for KMS in the second region. + decrypt_kms_client = boto3.client('kms', region_name=mrk_replica_decrypt_region) + + decrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( + kms_key_id=mrk_replica_key_id_decrypt, + kms_client=decrypt_kms_client + ) + + decrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( + input=decrypt_keyring_input + ) + + # 7. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=decrypt_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py new file mode 100644 index 000000000..38c5b1232 --- /dev/null +++ b/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py @@ -0,0 +1,183 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS MRK Multi Keyring + +The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to +create, encrypt, and decrypt data keys with AWS KMS MRK keys. +The KMS MRK multi-keyring consists of one or more individual keyrings of the +same or different type. The keys can either be regular KMS keys or MRKs. +The effect is like using several keyrings in a series. + +This example creates a AwsKmsMrkMultiKeyring using an mrk_key_id (generator) and a kms_key_id +as a child key, and then encrypts a custom input EXAMPLE_DATA with an encryption context. +Either KMS Key individually is capable of decrypting data encrypted under this keyring. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +4. Ciphertext can be decrypted using an AwsKmsMrkKeyring containing a replica of the + MRK (from the multi-keyring used for encryption) copied from the first region into + the second region +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html + +For more info on KMS MRK (multi-region keys), see the KMS documentation: +https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput, CreateAwsKmsMrkMultiKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + mrk_key_id: str, + kms_key_id: str, + mrk_replica_key_id: str, + mrk_replica_decrypt_region: str +): + """Demonstrate an encrypt/decrypt cycle using a Multi-Keyring made + up of multiple AWS KMS MRK Keyrings + + Usage: encrypt_and_decrypt_with_keyring(mrk_key_id, + kms_key_id, + mrk_replica_key_id, + mrk_replica_decrypt_region) + :param mrk_key_id: KMS Key identifier for an AWS KMS multi-region key (MRK) located in your + default region + :type mrk_key_id: string + :param kms_key_id: KMS Key identifier for a KMS key, possibly located in a different region + than the MRK + :type kms_key_id: string + :param mrk_replica_key_id: KMS Key identifier for an MRK that is a replica of the + `mrk_key_id` in a second region. + :type mrk_replica_key_id: string + :param mrk_replica_decrypt_region: The second region where the MRK replica is located + :type mrk_replica_decrypt_region: string + + For more information on KMS Key identifiers for multi-region keys, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create an AwsKmsMrkMultiKeyring that protects your data under two different KMS Keys. + # The Keys can either be regular KMS keys or MRKs. + # Either KMS Key individually is capable of decrypting data encrypted under this keyring. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + kms_mrk_multi_keyring_input: CreateAwsKmsMrkMultiKeyringInput =\ + CreateAwsKmsMrkMultiKeyringInput( + generator=mrk_key_id, + kms_key_ids=[kms_key_id] + ) + + kms_mrk_multi_keyring: IKeyring = mat_prov.create_aws_kms_mrk_multi_keyring( + input=kms_mrk_multi_keyring_input + ) + + # 4. Encrypt the data with the encryptionContext using the kms_mrk_multi_keyring. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=kms_mrk_multi_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6. Decrypt your encrypted data using the same AwsKmsMrkMultiKeyring you used on encrypt. + # It will decrypt the data using the generator key (in this case, the MRK), since that is + # the first available KMS key on the keyring that is capable of decrypting the data. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=kms_mrk_multi_keyring + ) + + # 7. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA + + # Demonstrate that a single AwsKmsMrkKeyring configured with a replica of the MRK from the + # multi-keyring used to encrypt the data is also capable of decrypting the data. + # (This is an example for demonstration; you do not need to do this in your own code.) + + # 9. Create a single AwsKmsMrkKeyring with the replica KMS MRK from the second region. + + # Create a boto3 client for KMS in the second region which is the region for mrk_replica_key_id. + second_region_kms_client = boto3.client('kms', region_name=mrk_replica_decrypt_region) + + second_region_mrk_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( + kms_key_id=mrk_replica_key_id, + kms_client=second_region_kms_client + ) + + second_region_mrk_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( + input=second_region_mrk_keyring_input + ) + + # 10. Decrypt your encrypted data using the second region AwsKmsMrkKeyring + plaintext_bytes_second_region, dec_header_second_region = client.decrypt( + source=ciphertext, + keyring=second_region_mrk_keyring + ) + + # 11. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header_second_region.encryption_context[k], \ + "Encryption context does not match expected values" + + # 12. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes_second_region == EXAMPLE_DATA + + # Not shown in this example: A KMS Keyring created with `kms_key_id` could also + # decrypt this message. diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py new file mode 100644 index 000000000..ab81d9c10 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py @@ -0,0 +1,22 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS MRK keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_mrk_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS MRK Keyring example.""" + mrk_key_id_encrypt = \ + "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + mrk_replica_key_id_decrypt = \ + "arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + mrk_encrypt_region = "us-east-1" + mrk_replica_decrypt_region = "eu-west-1" + encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + mrk_replica_key_id_decrypt, + mrk_encrypt_region, + mrk_replica_decrypt_region) diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py new file mode 100644 index 000000000..8272f3987 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py @@ -0,0 +1,23 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS MRK Multi keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_mrk_multi_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS MRK Multi Keyring example.""" + mrk_key_id = \ + "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + kms_key_id = \ + "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + mrk_replica_key_id = \ + "arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + mrk_replica_decrypt_region = "eu-west-1" + encrypt_and_decrypt_with_keyring(mrk_key_id, + kms_key_id, + mrk_replica_key_id, + mrk_replica_decrypt_region) From e47e4417713bec4d323a5c83be7857e4589b710c Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Mon, 6 May 2024 13:13:58 -0700 Subject: [PATCH 08/51] chore(examples): added mrk discovery keyring examples (#675) --- .../aws_kms_mrk_discovery_keyring_example.py | 185 +++++++++++++++++ ...kms_mrk_discovery_multi_keyring_example.py | 194 ++++++++++++++++++ ...r.py => branch_key_id_supplier_example.py} | 0 ...ing.py => hierarchical_keyring_example.py} | 2 +- ...i_aws_kms_mrk_discovery_keyring_example.py | 21 ++ ...kms_mrk_discovery_multi_keyring_example.py | 21 ++ ...=> test_i_hierarchical_keyring_example.py} | 2 +- 7 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py create mode 100644 examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py rename examples/src/keyrings/{example_branch_key_id_supplier.py => branch_key_id_supplier_example.py} (100%) rename examples/src/keyrings/{hierarchical_keyring.py => hierarchical_keyring_example.py} (99%) create mode 100644 examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py create mode 100644 examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py rename examples/test/keyrings/{test_i_hierarchical_keyring.py => test_i_hierarchical_keyring_example.py} (86%) diff --git a/examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py new file mode 100644 index 000000000..63233a068 --- /dev/null +++ b/examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py @@ -0,0 +1,185 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS MRK (multi-region key) Discovery Keyring + +The AWS KMS discovery keyring is an AWS KMS keyring that doesn't specify any wrapping keys. + +When decrypting, an MRK discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt +any encrypted data key by using the AWS KMS MRK that encrypted it, regardless of who owns or +has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt +permission on the AWS KMS MRK. + +The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring +for AWS KMS multi-Region keys. Because it doesn't specify any wrapping keys, a discovery keyring +can't encrypt data. If you use a discovery keyring to encrypt data, alone or in a multi-keyring, +the encrypt operation fails. + +The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to +create, encrypt, and decrypt data keys with multi-region AWS KMS keys (MRKs). +This example creates a KMS MRK Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This encrypted ciphertext is then decrypted using an +MRK Discovery keyring. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For information about using multi-Region keys with the AWS Encryption SDK, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks + +For more info on KMS MRKs (multi-region keys), see the KMS documentation: +https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html + +For more information on how to use KMS Discovery keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsMrkDiscoveryKeyringInput, + CreateAwsKmsMrkKeyringInput, + DiscoveryFilter, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + mrk_key_id_encrypt: str, + aws_account_id: str, + mrk_encrypt_region: str, + mrk_replica_decrypt_region: str +): + """Demonstrate decryption using an AWS KMS MRK Discovery keyring. + + Since discovery keyrings cannot be used to encrypt, we use KMS MRK keyring for encryption + Usage: encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + aws_account_id, + mrk_encrypt_region, + mrk_replica_decrypt_region) + :param mrk_key_id_encrypt: KMS Key identifier for the KMS key located in your + default region, which you want to use for encryption of your data keys + :type mrk_key_id_encrypt: string + :param aws_account_id: AWS Account ID to use in the discovery filter + :type aws_account_id: string + :param mrk_encrypt_region: AWS Region for encryption of your data keys. This should + be the region of the mrk_key_id_encrypt. + :type mrk_encrypt_region: string + :param mrk_replica_decrypt_region: AWS Region for decryption of your data keys. + This example assumes you have already replicated your mrk_key_id_encrypt to the + region mrk_replica_decrypt_region. Therefore, this mrk_replica_decrypt_region should + be the region of the MRK replica. However, since we are using a discovery keyring, + we don't need to provide the replica MRK ID. + :type mrk_replica_decrypt_region: string + + For more information on KMS Key identifiers for multi-region keys, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create the keyring that determines how your data keys are protected. + # Although this example highlights Discovery keyrings, Discovery keyrings cannot + # be used to encrypt, so for encryption we create an MRK keyring without discovery mode. + + # Create a keyring that will encrypt your data, using a KMS MRK in the first region. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create a boto3 client for KMS in the first region. + encrypt_kms_client = boto3.client('kms', region_name=mrk_encrypt_region) + + encrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( + kms_key_id=mrk_key_id_encrypt, + kms_client=encrypt_kms_client + ) + + encrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( + input=encrypt_keyring_input + ) + + # 4. Encrypt the data with the encryptionContext using the encrypt_keyring. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=encrypt_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6. Now create a Discovery keyring to use for decryption. + # In order to illustrate the MRK behavior of this keyring, we configure + # the keyring to use the second KMS region where the MRK (mrk_key_id_encrypt) is replicated to. + # This example assumes you have already replicated your key, but since we + # are using a discovery keyring, we don't need to provide the mrk replica key id + + # Create a boto3 client for KMS in the second region. + decrypt_kms_client = boto3.client('kms', region_name=mrk_replica_decrypt_region) + + decrypt_discovery_keyring_input: CreateAwsKmsMrkDiscoveryKeyringInput = \ + CreateAwsKmsMrkDiscoveryKeyringInput( + kms_client=decrypt_kms_client, + region=mrk_replica_decrypt_region, + discovery_filter=DiscoveryFilter( + account_ids=[aws_account_id], + partition="aws" + ) + ) + + decrypt_discovery_keyring: IKeyring = mat_prov.create_aws_kms_mrk_discovery_keyring( + input=decrypt_discovery_keyring_input + ) + + # 7. Decrypt your encrypted data using the discovery keyring. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=decrypt_discovery_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py new file mode 100644 index 000000000..d8ea9bc4c --- /dev/null +++ b/examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py @@ -0,0 +1,194 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the AWS KMS MRK (multi-region key) Discovery Multi Keyring + +AWS KMS MRK Discovery Multi Keyring is composed of multiple MRK discovery keyrings. + +The AWS KMS discovery keyring is an AWS KMS keyring that doesn't specify any wrapping keys. + +When decrypting, an MRK discovery keyring allows the AWS Encryption SDK to ask AWS KMS to decrypt +any encrypted data key by using the AWS KMS MRK that encrypted it, regardless of who owns or +has access to that AWS KMS key. The call succeeds only when the caller has kms:Decrypt +permission on the AWS KMS MRK. + +The AWS Encryption SDK provides a standard AWS KMS discovery keyring and a discovery keyring +for AWS KMS multi-Region keys. Because it doesn't specify any wrapping keys, a discovery keyring +can't encrypt data. If you use a discovery keyring to encrypt data, alone or in a multi-keyring, +the encrypt operation fails. + +The AWS Key Management Service (AWS KMS) MRK keyring interacts with AWS KMS to +create, encrypt, and decrypt data keys with multi-region AWS KMS keys (MRKs). +This example creates a KMS MRK Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context. This encrypted ciphertext is then decrypted using an +MRK Discovery Multi keyring. This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For information about using multi-Region keys with the AWS Encryption SDK, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks + +For more info on KMS MRKs (multi-region keys), see the KMS documentation: +https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html + +For more information on how to use KMS Discovery keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsMrkDiscoveryMultiKeyringInput, + CreateAwsKmsMrkKeyringInput, + DiscoveryFilter, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + mrk_key_id_encrypt: str, + mrk_encrypt_region: str, + aws_account_id: str, + aws_regions: list[str] +): + """Demonstrate decryption using an AWS KMS MRK Discovery Multi keyring. + + Since discovery keyrings cannot be used to encrypt, we use KMS MRK keyring for encryption + Usage: encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + mrk_encrypt_region, + aws_account_id, + aws_regions) + :param mrk_key_id_encrypt: KMS Key identifier for the KMS key located in your + default region, which you want to use for encryption of your data keys + :type mrk_key_id_encrypt: string + :param mrk_encrypt_region: AWS Region for encryption of your data keys. This should + be the region of the mrk_key_id_encrypt + :type mrk_encrypt_region: string + :param aws_account_id: AWS Account ID to use in the discovery filter + :type aws_account_id: string + :param aws_regions: AWS Regions to use in the the discovery filter + :type aws_regions: list[string] + + For more information on KMS Key identifiers for multi-region keys, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create the keyring that determines how your data keys are protected. + # Although this example highlights Discovery keyrings, Discovery keyrings cannot + # be used to encrypt, so for encryption we create an MRK keyring without discovery mode. + + # Create a keyring that will encrypt your data, using a KMS MRK in the first region. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create a boto3 client for KMS in the first region. + encrypt_kms_client = boto3.client('kms', region_name=mrk_encrypt_region) + + encrypt_keyring_input: CreateAwsKmsMrkKeyringInput = CreateAwsKmsMrkKeyringInput( + kms_key_id=mrk_key_id_encrypt, + kms_client=encrypt_kms_client + ) + + encrypt_keyring: IKeyring = mat_prov.create_aws_kms_mrk_keyring( + input=encrypt_keyring_input + ) + + # 4. Encrypt the data with the encryptionContext using the encrypt_keyring. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=encrypt_keyring, + encryption_context=encryption_context + ) + + # 5. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 6. Now create a MRK Discovery Multi Keyring to use for decryption. + # We'll add a discovery filter to limit the set of encrypted data keys + # we are willing to decrypt to only ones created by KMS keys in select + # accounts and the partition `aws`. + # MRK Discovery keyrings also filter encrypted data keys by the region + # the keyring is created with. + decrypt_discovery_multi_keyring_input: CreateAwsKmsMrkDiscoveryMultiKeyringInput = \ + CreateAwsKmsMrkDiscoveryMultiKeyringInput( + regions=aws_regions, + discovery_filter=DiscoveryFilter( + account_ids=[aws_account_id], + partition="aws" + ) + ) + + # This is a Multi Keyring composed of Discovery Keyrings. + # There is a keyring for every region in `regions`. + # All the keyrings have the same Discovery Filter. + # Each keyring has its own KMS Client, which is created for the keyring's region. + decrypt_discovery_keyring: IKeyring = mat_prov.create_aws_kms_mrk_discovery_multi_keyring( + input=decrypt_discovery_multi_keyring_input + ) + + # 7. Decrypt your encrypted data using the discovery multi keyring. + # On Decrypt, the header of the encrypted message (ciphertext) will be parsed. + # The header contains the Encrypted Data Keys (EDKs), which, if the EDK + # was encrypted by a KMS Keyring, includes the KMS Key ARN. + # For each member of the Multi Keyring, every EDK will try to be decrypted until a decryption + # is successful. + # Since every member of the Multi Keyring is a Discovery Keyring: + # Each Keyring will filter the EDKs by the Discovery Filter and the Keyring's region. + # For each filtered EDK, the keyring will attempt decryption with the keyring's client. + # All of this is done serially, until a success occurs or all keyrings have failed + # all (filtered) EDKs. KMS MRK Discovery Keyrings will attempt to decrypt + # Multi Region Keys (MRKs) and regular KMS Keys. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=decrypt_discovery_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/keyrings/example_branch_key_id_supplier.py b/examples/src/keyrings/branch_key_id_supplier_example.py similarity index 100% rename from examples/src/keyrings/example_branch_key_id_supplier.py rename to examples/src/keyrings/branch_key_id_supplier_example.py diff --git a/examples/src/keyrings/hierarchical_keyring.py b/examples/src/keyrings/hierarchical_keyring_example.py similarity index 99% rename from examples/src/keyrings/hierarchical_keyring.py rename to examples/src/keyrings/hierarchical_keyring_example.py index 5642a0b71..1edcab285 100644 --- a/examples/src/keyrings/hierarchical_keyring.py +++ b/examples/src/keyrings/hierarchical_keyring_example.py @@ -53,7 +53,7 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -from .example_branch_key_id_supplier import ExampleBranchKeyIdSupplier +from .branch_key_id_supplier_example import ExampleBranchKeyIdSupplier # TODO-MPL: Remove this as part of removing PYTHONPATH hacks. module_root_dir = '/'.join(__file__.split("/")[:-1]) diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py new file mode 100644 index 000000000..bc0279066 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py @@ -0,0 +1,21 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS MRK Discovery keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_mrk_discovery_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using the AWS KMS MRK Discovery Keyring example.""" + mrk_key_id_encrypt = \ + "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + aws_account_id = "658956600833" + mrk_encrypt_region = "us-east-1" + mrk_replica_decrypt_region = "eu-west-1" + encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + aws_account_id, + mrk_encrypt_region, + mrk_replica_decrypt_region) diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py b/examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py new file mode 100644 index 000000000..93672b046 --- /dev/null +++ b/examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py @@ -0,0 +1,21 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the AWS KMS MRK Discovery Multi keyring example.""" +import pytest + +from ...src.keyrings.aws_kms_mrk_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt using AWS KMS MRK Discovery Multi Keyring example.""" + mrk_key_id_encrypt = \ + "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7" + mrk_encrypt_region = "us-east-1" + aws_account_id = "658956600833" + aws_regions = ["us-west-2", "us-east-1"] + encrypt_and_decrypt_with_keyring(mrk_key_id_encrypt, + mrk_encrypt_region, + aws_account_id, + aws_regions) diff --git a/examples/test/keyrings/test_i_hierarchical_keyring.py b/examples/test/keyrings/test_i_hierarchical_keyring_example.py similarity index 86% rename from examples/test/keyrings/test_i_hierarchical_keyring.py rename to examples/test/keyrings/test_i_hierarchical_keyring_example.py index 5a3adaa1c..6b3f3850a 100644 --- a/examples/test/keyrings/test_i_hierarchical_keyring.py +++ b/examples/test/keyrings/test_i_hierarchical_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the hierarchical keyring example.""" import pytest -from ...src.keyrings.hierarchical_keyring import encrypt_and_decrypt_with_keyring +from ...src.keyrings.hierarchical_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] From 2a35192e4c5d2170e737a62150a99d1f44ce5fb9 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Tue, 7 May 2024 15:37:15 -0700 Subject: [PATCH 09/51] chore(examples): Added file_streaming, migration and set_encryption_algorithm_suite examples (#676) --- .gitignore | 2 +- .../aws_kms_discovery_keyring_example.py | 3 +- ...aws_kms_discovery_multi_keyring_example.py | 3 +- .../src/keyrings/aws_kms_keyring_example.py | 3 +- .../keyrings/aws_kms_mrk_keyring_example.py | 3 +- .../aws_kms_mrk_multi_keyring_example.py | 3 +- .../keyrings/aws_kms_multi_keyring_example.py | 9 +- .../keyrings/aws_kms_rsa_keyring_example.py | 3 +- .../src/keyrings/file_streaming_example.py | 152 ++++++++++++++++++ .../keyrings/hierarchical_keyring_example.py | 62 +++---- ...migration_set_commitment_policy_example.py | 128 +++++++++++++++ .../src/keyrings/multi_keyring_example.py | 9 +- .../src/keyrings/raw_aes_keyring_example.py | 3 +- .../src/keyrings/raw_rsa_keyring_example.py | 3 +- .../required_encryption_context_cmm.py | 14 +- .../set_encryption_algorithm_suite_example.py | 151 +++++++++++++++++ .../keyrings/test_i_file_streaming_example.py | 62 +++++++ ...migration_set_commitment_policy_example.py | 14 ++ .../test_i_raw_rsa_keyring_example.py | 26 +-- ..._set_encryption_algorithm_suite_example.py | 13 ++ 20 files changed, 602 insertions(+), 64 deletions(-) create mode 100644 examples/src/keyrings/file_streaming_example.py create mode 100644 examples/src/keyrings/migration_set_commitment_policy_example.py create mode 100644 examples/src/keyrings/set_encryption_algorithm_suite_example.py create mode 100644 examples/test/keyrings/test_i_file_streaming_example.py create mode 100644 examples/test/keyrings/test_i_migration_set_commitment_policy_example.py create mode 100644 examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py diff --git a/.gitignore b/.gitignore index 78bc3d5b8..24df397ed 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,7 @@ __pycache__ # PyTest .pytest_cache # Ignore key materials generated by examples or tests -test_keys/ +test_keyrings/ # PyCharm .idea/ diff --git a/examples/src/keyrings/aws_kms_discovery_keyring_example.py b/examples/src/keyrings/aws_kms_discovery_keyring_example.py index 24dc111f1..53d9cf1e4 100644 --- a/examples/src/keyrings/aws_kms_discovery_keyring_example.py +++ b/examples/src/keyrings/aws_kms_discovery_keyring_example.py @@ -172,7 +172,8 @@ def encrypt_and_decrypt_with_keyring( # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # 11. Demonstrate that if a discovery keyring (Bob's) doesn't have the correct AWS Account ID's, # the decrypt will fail with an error message diff --git a/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py b/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py index 0830ecb58..adfadec37 100644 --- a/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py @@ -170,4 +170,5 @@ def encrypt_and_decrypt_with_keyring( # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/aws_kms_keyring_example.py b/examples/src/keyrings/aws_kms_keyring_example.py index fa7ffd12f..4d04ba538 100644 --- a/examples/src/keyrings/aws_kms_keyring_example.py +++ b/examples/src/keyrings/aws_kms_keyring_example.py @@ -116,4 +116,5 @@ def encrypt_and_decrypt_with_keyring( # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/aws_kms_mrk_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_keyring_example.py index b82748cf9..d5342ba64 100644 --- a/examples/src/keyrings/aws_kms_mrk_keyring_example.py +++ b/examples/src/keyrings/aws_kms_mrk_keyring_example.py @@ -151,4 +151,5 @@ def encrypt_and_decrypt_with_keyring( # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py b/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py index 38c5b1232..e5445a87c 100644 --- a/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py @@ -143,7 +143,8 @@ def encrypt_and_decrypt_with_keyring( # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # Demonstrate that a single AwsKmsMrkKeyring configured with a replica of the MRK from the # multi-keyring used to encrypt the data is also capable of decrypting the data. diff --git a/examples/src/keyrings/aws_kms_multi_keyring_example.py b/examples/src/keyrings/aws_kms_multi_keyring_example.py index 0e556f5e3..9662405d6 100644 --- a/examples/src/keyrings/aws_kms_multi_keyring_example.py +++ b/examples/src/keyrings/aws_kms_multi_keyring_example.py @@ -144,7 +144,8 @@ def encrypt_and_decrypt_with_keyring( # 6b. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_multi_keyring == EXAMPLE_DATA + assert plaintext_bytes_multi_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # Because you used a multi_keyring on Encrypt, you can use either of the two # kms keyrings individually to decrypt the data. @@ -174,7 +175,8 @@ def encrypt_and_decrypt_with_keyring( # 7d. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_default_region_kms_keyring == EXAMPLE_DATA + assert plaintext_bytes_default_region_kms_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # 8. Demonstrate that you can also successfully decrypt data using a KMS keyring with just the # `second_region_kms_key_id` directly. @@ -201,4 +203,5 @@ def encrypt_and_decrypt_with_keyring( # 8d. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_second_region_kms_keyring == EXAMPLE_DATA + assert plaintext_bytes_second_region_kms_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/aws_kms_rsa_keyring_example.py b/examples/src/keyrings/aws_kms_rsa_keyring_example.py index 5c0bbe736..536581eb8 100644 --- a/examples/src/keyrings/aws_kms_rsa_keyring_example.py +++ b/examples/src/keyrings/aws_kms_rsa_keyring_example.py @@ -122,4 +122,5 @@ def encrypt_and_decrypt_with_keyring( # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/file_streaming_example.py b/examples/src/keyrings/file_streaming_example.py new file mode 100644 index 000000000..b7352ba0e --- /dev/null +++ b/examples/src/keyrings/file_streaming_example.py @@ -0,0 +1,152 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example demonstrates file streaming for encryption and decryption. + +File streaming is useful when the plaintext or ciphertext file/data is too large to load into +memory. Therefore, the AWS Encryption SDK allows users to stream the data, instead of loading it +all at once in memory. In this example, we demonstrate file streaming for encryption and decryption +using a Raw AES keyring. However, you can use any keyring with streaming. + +This example creates a Raw AES Keyring and then encrypts an input stream from the file +`plaintext_filename` with an encryption context to an output (encrypted) file `ciphertext_filename`. +It then decrypts the ciphertext from `ciphertext_filename` to a new file `decrypted_filename`. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html + +See raw_aes_keyring_example.py in the same directory for another raw AES keyring example +in the AWS Encryption SDK for Python. +""" +import filecmp +import secrets +import sys + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + + +def encrypt_and_decrypt_with_keyring( + plaintext_filename: str, + ciphertext_filename: str, + decrypted_filename: str +): + """Demonstrate a streaming encrypt/decrypt cycle. + + Usage: encrypt_and_decrypt_with_keyring(plaintext_filename + ciphertext_filename + decrypted_filename) + :param plaintext_filename: filename of the plaintext data + :type plaintext_filename: string + :param ciphertext_filename: filename of the ciphertext data + :type ciphertext_filename: string + :param decrypted_filename: filename of the decrypted data + :type decrypted_filename: string + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. The key namespace and key name are defined by you. + # and are used by the Raw AES keyring to determine + # whether it should attempt to decrypt an encrypted data key. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Generate a 256-bit AES key to use with your keyring. + # In practice, you should get this key from a secure key management system such as an HSM. + + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + static_key = secrets.token_bytes(32) + + # 5. Create a Raw AES keyring + # We choose to use a raw AES keyring, but any keyring can be used with streaming. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + # 6. Encrypt the data stream with the encryptionContext + with open(plaintext_filename, 'rb') as pt_file, open(ciphertext_filename, 'wb') as ct_file: + with client.stream( + mode='e', + source=pt_file, + keyring=raw_aes_keyring, + encryption_context=encryption_context + ) as encryptor: + for chunk in encryptor: + ct_file.write(chunk) + + # 7. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert not filecmp.cmp(plaintext_filename, ciphertext_filename), \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 8. Decrypt your encrypted data stream using the same keyring you used on encrypt. + with open(ciphertext_filename, 'rb') as ct_file, open(decrypted_filename, 'wb') as pt_file: + with client.stream( + mode='d', + source=ct_file, + keyring=raw_aes_keyring, + encryption_context=encryption_context + ) as decryptor: + for chunk in decryptor: + pt_file.write(chunk) + + # 9. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == decryptor.header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert filecmp.cmp(plaintext_filename, decrypted_filename), \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/hierarchical_keyring_example.py b/examples/src/keyrings/hierarchical_keyring_example.py index 1edcab285..7020b68b4 100644 --- a/examples/src/keyrings/hierarchical_keyring_example.py +++ b/examples/src/keyrings/hierarchical_keyring_example.py @@ -101,13 +101,13 @@ def encrypt_and_decrypt_with_keyring( ) # 4. Call CreateKey to create two new active branch keys - branch_key_id_A: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier - branch_key_id_B: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier + branch_key_id_a: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier + branch_key_id_b: str = keystore.create_key(input=CreateKeyInput()).branch_key_identifier # 5. Create a branch key supplier that maps the branch key id to a more readable format branch_key_id_supplier: IBranchKeyIdSupplier = ExampleBranchKeyIdSupplier( - tenant_1_id=branch_key_id_A, - tenant_2_id=branch_key_id_B, + tenant_1_id=branch_key_id_a, + tenant_2_id=branch_key_id_b, ) # 6. Create the Hierarchical Keyring. @@ -135,7 +135,7 @@ def encrypt_and_decrypt_with_keyring( # be used to encrypt data. # Create encryption context for TenantA - encryption_context_A: Dict[str, str] = { + encryption_context_a: Dict[str, str] = { "tenant": "TenantA", "encryption": "context", "is not": "secret", @@ -145,7 +145,7 @@ def encrypt_and_decrypt_with_keyring( } # Create encryption context for TenantB - encryption_context_B: Dict[str, str] = { + encryption_context_b: Dict[str, str] = { "tenant": "TenantB", "encryption": "context", "is not": "secret", @@ -155,22 +155,22 @@ def encrypt_and_decrypt_with_keyring( } # 8. Encrypt the data with encryptionContextA & encryptionContextB - ciphertext_A, _ = client.encrypt( + ciphertext_a, _ = client.encrypt( source=EXAMPLE_DATA, keyring=hierarchical_keyring, - encryption_context=encryption_context_A + encryption_context=encryption_context_a ) - ciphertext_B, _ = client.encrypt( + ciphertext_b, _ = client.encrypt( source=EXAMPLE_DATA, keyring=hierarchical_keyring, - encryption_context=encryption_context_B + encryption_context=encryption_context_b ) # 9. To attest that TenantKeyB cannot decrypt a message written by TenantKeyA, # let's construct more restrictive hierarchical keyrings. - keyring_input_A: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + keyring_input_a: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, - branch_key_id=branch_key_id_A, + branch_key_id=branch_key_id_a, ttl_seconds=600, cache=CacheTypeDefault( value=DefaultCache( @@ -179,13 +179,13 @@ def encrypt_and_decrypt_with_keyring( ), ) - hierarchical_keyring_A: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( - input=keyring_input_A + hierarchical_keyring_a: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input_a ) - keyring_input_B: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + keyring_input_b: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, - branch_key_id=branch_key_id_B, + branch_key_id=branch_key_id_b, ttl_seconds=600, cache=CacheTypeDefault( value=DefaultCache( @@ -194,8 +194,8 @@ def encrypt_and_decrypt_with_keyring( ), ) - hierarchical_keyring_B: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( - input=keyring_input_B + hierarchical_keyring_b: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input_b ) # 10. Demonstrate that data encrypted by one tenant's key @@ -205,8 +205,8 @@ def encrypt_and_decrypt_with_keyring( # This will fail and raise a AWSEncryptionSDKClientError, which we swallow ONLY for demonstration purposes. try: client.decrypt( - source=ciphertext_A, - keyring=hierarchical_keyring_B + source=ciphertext_a, + keyring=hierarchical_keyring_b ) except AWSEncryptionSDKClientError: pass @@ -215,21 +215,23 @@ def encrypt_and_decrypt_with_keyring( # This will fail and raise a AWSEncryptionSDKClientError, which we swallow ONLY for demonstration purposes. try: client.decrypt( - source=ciphertext_B, - keyring=hierarchical_keyring_A + source=ciphertext_b, + keyring=hierarchical_keyring_a ) except AWSEncryptionSDKClientError: pass # 10. Demonstrate that data encrypted by one tenant's branch key can be decrypted by that tenant, # and that the decrypted data matches the input data. - plaintext_bytes_A, _ = client.decrypt( - source=ciphertext_A, - keyring=hierarchical_keyring_A + plaintext_bytes_a, _ = client.decrypt( + source=ciphertext_a, + keyring=hierarchical_keyring_a ) - assert plaintext_bytes_A == EXAMPLE_DATA - plaintext_bytes_B, _ = client.decrypt( - source=ciphertext_B, - keyring=hierarchical_keyring_B + assert plaintext_bytes_a == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" + plaintext_bytes_b, _ = client.decrypt( + source=ciphertext_b, + keyring=hierarchical_keyring_b ) - assert plaintext_bytes_B == EXAMPLE_DATA + assert plaintext_bytes_b == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/migration_set_commitment_policy_example.py b/examples/src/keyrings/migration_set_commitment_policy_example.py new file mode 100644 index 000000000..0a9e6a3a6 --- /dev/null +++ b/examples/src/keyrings/migration_set_commitment_policy_example.py @@ -0,0 +1,128 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example configures a client with a specific commitment policy for the +AWS Encryption SDK client, then encrypts and decrypts data using an AWS KMS Keyring. + +The commitment policy in this example (FORBID_ENCRYPT_ALLOW_DECRYPT) should only be +used as part of a migration from version 1.x to 2.x, or for advanced users with +specialized requirements. Most AWS Encryption SDK users should use the default +commitment policy (REQUIRE_ENCRYPT_REQUIRE_DECRYPT). + +This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context for the commitment policy FORBID_ENCRYPT_ALLOW_DECRYPT. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on setting your commitment policy, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#commitment-policy +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring( + kms_key_id: str +): + """Demonstrate how to set your commitment policy for migration. + + Usage: encrypt_and_decrypt_with_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This example builds the client with the FORBID_ENCRYPT_ALLOW_DECRYPT commitment policy, + # which enforces that this client cannot encrypt with key commitment + # and it can decrypt ciphertexts encrypted with or without key commitment. + # The default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()` is REQUIRE_ENCRYPT_REQUIRE_DECRYPT. + # We recommend that AWS Encryption SDK users use the default commitment policy + # (REQUIRE_ENCRYPT_REQUIRE_DECRYPT) whenever possible. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + ) + + # 2. Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name="us-west-2") + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # 5. Encrypt the data with the encryptionContext. Make sure you use a non-committing algorithm + # with the commitment policy FORBID_ENCRYPT_ALLOW_DECRYPT. Otherwise client.encrypt() will throw + # aws_encryption_sdk.exceptions.ActionNotAllowedError. By default for + # FORBID_ENCRYPT_ALLOW_DECRYPT, the algorithm used is + # AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 which is a non-committing algorithm. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=kms_keyring, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=kms_keyring + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/multi_keyring_example.py b/examples/src/keyrings/multi_keyring_example.py index 58e4839ac..fd9968f59 100644 --- a/examples/src/keyrings/multi_keyring_example.py +++ b/examples/src/keyrings/multi_keyring_example.py @@ -175,7 +175,8 @@ def encrypt_and_decrypt_with_keyring( # 10b. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_multi_keyring == EXAMPLE_DATA + assert plaintext_bytes_multi_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # Because you used a multi_keyring on Encrypt, you can use either the # `kms_keyring` or `raw_aes_keyring` individually to decrypt the data. @@ -192,7 +193,8 @@ def encrypt_and_decrypt_with_keyring( # 11b. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_kms_keyring == EXAMPLE_DATA + assert plaintext_bytes_kms_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # 12. Demonstrate that you can also successfully decrypt data using the `raw_aes_keyring` # directly. @@ -206,4 +208,5 @@ def encrypt_and_decrypt_with_keyring( # 12b. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes_raw_aes_keyring == EXAMPLE_DATA + assert plaintext_bytes_raw_aes_keyring == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/raw_aes_keyring_example.py b/examples/src/keyrings/raw_aes_keyring_example.py index ee0ab7618..be37886da 100644 --- a/examples/src/keyrings/raw_aes_keyring_example.py +++ b/examples/src/keyrings/raw_aes_keyring_example.py @@ -126,4 +126,5 @@ def encrypt_and_decrypt_with_keyring(): # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/keyrings/raw_rsa_keyring_example.py b/examples/src/keyrings/raw_rsa_keyring_example.py index 49d868a86..faf617209 100644 --- a/examples/src/keyrings/raw_rsa_keyring_example.py +++ b/examples/src/keyrings/raw_rsa_keyring_example.py @@ -224,7 +224,8 @@ def encrypt_and_decrypt_with_keyring(public_key_file_name=None, private_key_file # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) - assert plaintext_bytes == EXAMPLE_DATA + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # The next part of the example creates a new RSA keyring (for Bob) to demonstrate that # decryption of the original ciphertext is not possible with a different keyring (Bob's). diff --git a/examples/src/keyrings/required_encryption_context_cmm.py b/examples/src/keyrings/required_encryption_context_cmm.py index e0c19697c..3f106c5ee 100644 --- a/examples/src/keyrings/required_encryption_context_cmm.py +++ b/examples/src/keyrings/required_encryption_context_cmm.py @@ -108,26 +108,28 @@ def encrypt_and_decrypt_with_keyring( } # 8. Decrypt the data - plaintext_bytes_A, _ = client.decrypt( + plaintext_bytes_a, _ = client.decrypt( source=ciphertext, materials_manager=required_ec_cmm, encryption_context=reproduced_encryption_context ) - assert plaintext_bytes_A == EXAMPLE_DATA + assert plaintext_bytes_a == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # We can also decrypt using the underlying CMM, # but must also provide the reproduced encryption context - plaintext_bytes_A, _ = client.decrypt( + plaintext_bytes_a, _ = client.decrypt( source=ciphertext, materials_manager=underlying_cmm, encryption_context=reproduced_encryption_context ) - assert plaintext_bytes_A == EXAMPLE_DATA + assert plaintext_bytes_a == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" # 9. Extra: Demonstrate that if we don't provide the reproduced encryption context, # decryption will fail. try: - plaintext_bytes_A, _ = client.decrypt( + plaintext_bytes_a, _ = client.decrypt( source=ciphertext, materials_manager=required_ec_cmm, # No reproduced encryption context for required EC CMM-produced message makes decryption fail. @@ -143,7 +145,7 @@ def encrypt_and_decrypt_with_keyring( # Same for the default CMM; # If we don't provide the reproduced encryption context, decryption will fail. try: - plaintext_bytes_A, _ = client.decrypt( + plaintext_bytes_a, _ = client.decrypt( source=ciphertext, materials_manager=required_ec_cmm, # No reproduced encryption context for required EC CMM-produced message makes decryption fail. diff --git a/examples/src/keyrings/set_encryption_algorithm_suite_example.py b/examples/src/keyrings/set_encryption_algorithm_suite_example.py new file mode 100644 index 000000000..c14eb4bb3 --- /dev/null +++ b/examples/src/keyrings/set_encryption_algorithm_suite_example.py @@ -0,0 +1,151 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example demonstrates how to set an algorithm suite while using the Raw AES Keyring +in the AWS Encryption SDK. + +The algorithm suite used in the encrypt() method is the algorithm used to protect your +data using the data key. By setting this algorithm, you can configure the algorithm used +to encrypt and decrypt your data. + +Algorithm suites can be set in a similar manner in other keyrings as well. However, +please make sure that you're using a logical algorithm suite that is compatible with your +keyring. For more information on algorithm suites supported by the AWS Encryption SDK, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/supported-algorithms.html + +The AES wrapping algorithm (AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16) protects your data key using +the user-provided wrapping key. In contrast, the algorithm suite used in the encrypt() method +is the algorithm used to protect your data using the data key. This example demonstrates setting the +latter, which is the algorithm suite for protecting your data. When the commitment policy is +REQUIRE_ENCRYPT_REQUIRE_DECRYPT, the default algorithm used in the encrypt method is +AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, which is a committing and signing algorithm. +Signature verification ensures the integrity of a digital message as it goes across trust +boundaries. However, signature verification adds a significant performance cost to encryption +and decryption. If encryptors and decryptors are equally trusted, we can consider using an algorithm +suite that does not include signing. This example sets the algorithm suite as +AES_256_GCM_HKDF_SHA512_COMMIT_KEY, which is a committing but non-signing algorithm. +For more information on digital signatures, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#digital-sigs + +This example creates a Raw AES Keyring and then encrypts a custom input EXAMPLE_DATA +with an encryption context and the algorithm suite AES_256_GCM_HKDF_SHA512_COMMIT_KEY. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html +""" +import secrets +import sys + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.identifiers import AlgorithmSuite + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_keyring(): + """Demonstrate an encrypt/decrypt cycle using a Raw AES keyring. + + Usage: encrypt_and_decrypt_with_keyring() + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. The key namespace and key name are defined by you. + # and are used by the Raw AES keyring to determine + # whether it should attempt to decrypt an encrypted data key. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # 3. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 4. Generate a 256-bit AES wrapping key to use with your keyring. + # In practice, you should get this key from a secure key management system such as an HSM. + + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + static_key = secrets.token_bytes(32) + + # 5. Create a Raw AES keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # The wrapping algorithm here is NOT the algorithm suite we set in this example. + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + # 6. Encrypt the data with the encryptionContext. + # This is the important step in this example where we specify the algorithm suite + # you want to use for encrypting your data + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_aes_keyring, + encryption_context=encryption_context, + algorithm=AlgorithmSuite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY + ) + + # 7. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 8. Decrypt your encrypted data using the same keyring you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + keyring=raw_aes_keyring + ) + + # 9. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/test/keyrings/test_i_file_streaming_example.py b/examples/test/keyrings/test_i_file_streaming_example.py new file mode 100644 index 000000000..2e502f185 --- /dev/null +++ b/examples/test/keyrings/test_i_file_streaming_example.py @@ -0,0 +1,62 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the file streaming keyring example.""" +import os + +import pytest + +from ...src.keyrings.file_streaming_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for encrypt and decrypt for file streaming example using Raw AES keyring.""" + test_keyrings_directory = 'test_keyrings' + if not os.path.exists(test_keyrings_directory): + os.makedirs(test_keyrings_directory) + + # Define the filename of the input plaintext data. + plaintext_filename = test_keyrings_directory + '/my-secret-data.dat' + + # Define the plaintext data to be encrypted and decrypted. + plaintext_data = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. +Praesent non feugiat leo. Aenean iaculis tellus ut velit consectetur, +quis convallis orci eleifend. Sed eu dictum sapien. Nulla facilisi. Suspendisse potenti. +Proin vehicula vehicula maximus. Donec varius et elit vel rutrum. Nulla lacinia neque turpis +quis consequat orci pharetra et. Etiam consequat ullamcorper mauris. Vivamus molestie mollis +mauris a gravida. Curabitur sed bibendum nisl. Cras varius tortor non erat sodales, quis congu +tellus laoreet. Etiam fermentum purus eu diam sagittis, vitae commodo est vehicula. +Nulla feugiat viverra orci vel interdum. Quisque pulvinar elit eget nulla facilisis varius. +Mauris at suscipit sem. Aliquam in purus ut velit fringilla volutpat id non mi. +Curabitur quis nunc eleifend, ornare lectus non, fringilla quam. Nam maximus volutpat placerat. +Nulla ullamcorper lorem velit, nec sagittis ex tristique posuere. Aliquam fringilla magna commod +libero faucibus tempor. Vestibulum non ligula tincidunt, finibus sapien in, sollicitudin +ex. Pellentesque congue laoreet mi in condimentum. Cras convallis nisi ac nunc tincidunt +venenatis. Suspendisse urna elit, cursus eu lacus a, aliquet porttitor mi. +Nulla vel congue nibh, sed condimentum dui. Ut ante ligula, blandit eu finibus nec, +scelerisque quis eros. Maecenas gravida odio eget nibh dictum, dictum varius lacus interdum. +Integer quis nulla vulputate, rhoncus diam vitae, mollis mauris. Sed ut porttitor dolor. +Fusce ut justo a ex bibendum imperdiet nec sit amet magna. Sed ullamcorper luctus augue, +tempor viverra elit interdum sed. Cras sit amet arcu eu turpis molestie sollicitudin. +Curabitur fermentum varius nibh, ut aliquet nisi. Aliquam id tempus tellus. +Nulla porttitor nulla at nibh interdum, quis sollicitudin erat egestas. +Ut blandit mauris quis efficitur efficitur. Morbi neque sapien, posuere ut aliquam eget, +aliquam at velit. Morbi sit amet rhoncus felis, et hendrerit sem. Nulla porta dictum ligula +eget iaculis. Cras lacinia ligula quis risus ultrices, sed consectetur metus imperdiet. +Nullam id enim vestibulum nibh ultricies auctor. Morbi neque lacus, faucibus vitae commodo quis, +malesuada sed velit.''' + + # Write plaintext data to plaintext_filename file + with open(plaintext_filename, "w", encoding="utf-8") as f: + f.write(plaintext_data) + + # Define the filename of the encrypted data. + ciphertext_filename = test_keyrings_directory + '/my-encrypted-data.ct' + + # Define the filename of the decrypted data. + decrypted_filename = test_keyrings_directory + '/my-decrypted-data.dat' + + encrypt_and_decrypt_with_keyring(plaintext_filename, + ciphertext_filename, + decrypted_filename) diff --git a/examples/test/keyrings/test_i_migration_set_commitment_policy_example.py b/examples/test/keyrings/test_i_migration_set_commitment_policy_example.py new file mode 100644 index 000000000..7580ed670 --- /dev/null +++ b/examples/test/keyrings/test_i_migration_set_commitment_policy_example.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_set_commitment_policy_example.""" +import pytest + +from ...src.keyrings.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for setting commitment policy using the AWS KMS Keyring example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_keyring(kms_key_id) diff --git a/examples/test/keyrings/test_i_raw_rsa_keyring_example.py b/examples/test/keyrings/test_i_raw_rsa_keyring_example.py index e036eb0b0..87786b4b3 100644 --- a/examples/test/keyrings/test_i_raw_rsa_keyring_example.py +++ b/examples/test/keyrings/test_i_raw_rsa_keyring_example.py @@ -32,13 +32,13 @@ def test_encrypt_and_decrypt_with_keyring_with_user_defined_keys(): user_public_key = user_public_key.decode('utf-8') user_private_key = user_private_key.decode('utf-8') - test_keys_directory = 'test_keys' - if not os.path.exists(test_keys_directory): - os.makedirs(test_keys_directory) + test_keyrings_directory = 'test_keyrings' + if not os.path.exists(test_keyrings_directory): + os.makedirs(test_keyrings_directory) # Define the file names for the keys - user_public_key_file_name = test_keys_directory + '/user_public_key_file_name.pem' - user_private_key_file_name = test_keys_directory + '/user_private_key_file_name.pem' + user_public_key_file_name = test_keyrings_directory + '/user_public_key_file_name.pem' + user_private_key_file_name = test_keyrings_directory + '/user_private_key_file_name.pem' # Write the public key to the file with open(user_public_key_file_name, "w", encoding="utf-8") as f: @@ -65,12 +65,12 @@ def test_encrypt_and_decrypt_fails_if_user_provides_only_public_key(): # Convert the public key to string user_public_key = user_public_key.decode('utf-8') - test_keys_directory = 'test_keys' - if not os.path.exists(test_keys_directory): - os.makedirs(test_keys_directory) + test_keyrings_directory = 'test_keyrings' + if not os.path.exists(test_keyrings_directory): + os.makedirs(test_keyrings_directory) # Define the file name for the public key - user_public_key_file_name = test_keys_directory + '/user_public_key_file_name.pem' + user_public_key_file_name = test_keyrings_directory + '/user_public_key_file_name.pem' # Write the public key to the file with open(user_public_key_file_name, "w", encoding="utf-8") as f: @@ -97,12 +97,12 @@ def test_encrypt_and_decrypt_fails_if_user_provides_only_private_key(): # Convert the private key to string user_private_key = user_private_key.decode('utf-8') - test_keys_directory = 'test_keys' - if not os.path.exists(test_keys_directory): - os.makedirs(test_keys_directory) + test_keyrings_directory = 'test_keyrings' + if not os.path.exists(test_keyrings_directory): + os.makedirs(test_keyrings_directory) # Define the file name for the private key - user_private_key_file_name = test_keys_directory + '/user_private_key_file_name.pem' + user_private_key_file_name = test_keyrings_directory + '/user_private_key_file_name.pem' # Write the private key to the file with open(user_private_key_file_name, "w", encoding="utf-8") as f: diff --git a/examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py b/examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py new file mode 100644 index 000000000..0703bc961 --- /dev/null +++ b/examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py @@ -0,0 +1,13 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Set Algorithm Suite example for a Raw AES keyring.""" +import pytest + +from ...src.keyrings.set_encryption_algorithm_suite_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(): + """Test function for setting an algorithm suite in a Raw AES Keyring.""" + encrypt_and_decrypt_with_keyring() From 986f54c864e945399b0de63ea91f1ff471daf410 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 7 May 2024 17:09:50 -0700 Subject: [PATCH 10/51] feat(test_vector_handlers): TestVectors test with MPL constructs (#650) --- buildspec.yml | 258 ++++++++++++++++-- .../py310/decrypt_dafny_esdk_vectors.yml | 58 ++++ codebuild/py310/decrypt_masterkey_with_js.yml | 34 +++ .../decrypt_masterkey_with_masterkey.yml | 30 ++ codebuild/py310/decrypt_net_401_vectors.yml | 35 +++ codebuild/py310/encrypt_masterkey.yml | 25 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ .../decrypt_dafny_esdk_vectors_keyrings.yml | 59 ++++ .../decrypt_dafny_esdk_vectors_masterkey.yml | 58 ++++ codebuild/py311/decrypt_keyrings_with_js.yml | 34 +++ .../py311/decrypt_keyrings_with_keyrings.yml | 31 +++ .../py311/decrypt_keyrings_with_masterkey.yml | 30 ++ codebuild/py311/decrypt_masterkey_with_js.yml | 34 +++ .../py311/decrypt_masterkey_with_keyrings.yml | 31 +++ .../decrypt_masterkey_with_masterkey.yml | 30 ++ .../decrypt_net_401_vectors_keyrings.yml | 36 +++ .../decrypt_net_401_vectors_masterkey.yml | 45 +++ codebuild/py311/encrypt_keyrings.yml | 26 ++ codebuild/py311/encrypt_masterkey.yml | 25 ++ .../generate_decrypt_vectors_keyrings.yml | 29 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ codebuild/py312/awses_local.yml | 7 +- codebuild/py312/awses_local_mpl.yml | 2 +- .../decrypt_dafny_esdk_vectors_keyrings.yml | 59 ++++ .../decrypt_dafny_esdk_vectors_masterkey.yml | 58 ++++ codebuild/py312/decrypt_keyrings_with_js.yml | 34 +++ .../py312/decrypt_keyrings_with_keyrings.yml | 31 +++ .../py312/decrypt_keyrings_with_masterkey.yml | 30 ++ codebuild/py312/decrypt_masterkey_with_js.yml | 34 +++ .../py312/decrypt_masterkey_with_keyrings.yml | 31 +++ .../decrypt_masterkey_with_masterkey.yml | 30 ++ .../decrypt_net_401_vectors_keyrings.yml | 36 +++ .../decrypt_net_401_vectors_masterkey.yml | 45 +++ codebuild/py312/encrypt_keyrings.yml | 26 ++ codebuild/py312/encrypt_masterkey.yml | 25 ++ codebuild/py312/examples.yml | 7 +- codebuild/py312/examples_mpl.yml | 4 +- .../generate_decrypt_vectors_keyrings.yml | 29 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ codebuild/py312/integ.yml | 7 +- codebuild/py312/integ_mpl.yml | 2 +- codebuild/py37/decrypt_dafny_esdk_vectors.yml | 58 ++++ codebuild/py37/decrypt_masterkey_with_js.yml | 34 +++ .../py37/decrypt_masterkey_with_masterkey.yml | 30 ++ codebuild/py37/decrypt_net_401_vectors.yml | 35 +++ codebuild/py37/encrypt_masterkey.yml | 25 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ codebuild/py38/decrypt_dafny_esdk_vectors.yml | 58 ++++ codebuild/py38/decrypt_masterkey_with_js.yml | 34 +++ .../py38/decrypt_masterkey_with_masterkey.yml | 30 ++ codebuild/py38/decrypt_net_401_vectors.yml | 35 +++ codebuild/py38/encrypt_masterkey.yml | 25 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ codebuild/py39/decrypt_dafny_esdk_vectors.yml | 58 ++++ codebuild/py39/decrypt_masterkey_with_js.yml | 34 +++ .../py39/decrypt_masterkey_with_masterkey.yml | 30 ++ codebuild/py39/decrypt_net_401_vectors.yml | 35 +++ codebuild/py39/encrypt_masterkey.yml | 25 ++ .../generate_decrypt_vectors_masterkey.yml | 28 ++ .../internal/crypto/wrapping_keys.py | 9 +- .../internal/formatting/deserialize.py | 2 +- test_vector_handlers/requirements_mpl.txt | 1 + .../commands/full_message_decrypt.py | 19 +- .../commands/full_message_decrypt_generate.py | 18 +- .../commands/full_message_encrypt.py | 19 +- .../internal/mpl/__init__.py | 3 + .../internal/mpl/keyvectors_provider.py | 27 ++ .../internal/mpl/tampering_mpl_materials.py | 179 ++++++++++++ .../manifests/full_message/decrypt.py | 251 ++++++++++++++++- .../full_message/decrypt_generation.py | 169 ++++++++++-- .../manifests/full_message/encrypt.py | 54 +++- .../manifests/mpl_keyring.py | 182 ++++++++++++ test_vector_handlers/tox.ini | 9 +- 73 files changed, 2971 insertions(+), 90 deletions(-) create mode 100644 codebuild/py310/decrypt_dafny_esdk_vectors.yml create mode 100644 codebuild/py310/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py310/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py310/decrypt_net_401_vectors.yml create mode 100644 codebuild/py310/encrypt_masterkey.yml create mode 100644 codebuild/py310/generate_decrypt_vectors_masterkey.yml create mode 100644 codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml create mode 100644 codebuild/py311/decrypt_dafny_esdk_vectors_masterkey.yml create mode 100644 codebuild/py311/decrypt_keyrings_with_js.yml create mode 100644 codebuild/py311/decrypt_keyrings_with_keyrings.yml create mode 100644 codebuild/py311/decrypt_keyrings_with_masterkey.yml create mode 100644 codebuild/py311/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py311/decrypt_masterkey_with_keyrings.yml create mode 100644 codebuild/py311/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py311/decrypt_net_401_vectors_keyrings.yml create mode 100644 codebuild/py311/decrypt_net_401_vectors_masterkey.yml create mode 100644 codebuild/py311/encrypt_keyrings.yml create mode 100644 codebuild/py311/encrypt_masterkey.yml create mode 100644 codebuild/py311/generate_decrypt_vectors_keyrings.yml create mode 100644 codebuild/py311/generate_decrypt_vectors_masterkey.yml create mode 100644 codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml create mode 100644 codebuild/py312/decrypt_dafny_esdk_vectors_masterkey.yml create mode 100644 codebuild/py312/decrypt_keyrings_with_js.yml create mode 100644 codebuild/py312/decrypt_keyrings_with_keyrings.yml create mode 100644 codebuild/py312/decrypt_keyrings_with_masterkey.yml create mode 100644 codebuild/py312/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py312/decrypt_masterkey_with_keyrings.yml create mode 100644 codebuild/py312/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py312/decrypt_net_401_vectors_keyrings.yml create mode 100644 codebuild/py312/decrypt_net_401_vectors_masterkey.yml create mode 100644 codebuild/py312/encrypt_keyrings.yml create mode 100644 codebuild/py312/encrypt_masterkey.yml create mode 100644 codebuild/py312/generate_decrypt_vectors_keyrings.yml create mode 100644 codebuild/py312/generate_decrypt_vectors_masterkey.yml create mode 100644 codebuild/py37/decrypt_dafny_esdk_vectors.yml create mode 100644 codebuild/py37/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py37/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py37/decrypt_net_401_vectors.yml create mode 100644 codebuild/py37/encrypt_masterkey.yml create mode 100644 codebuild/py37/generate_decrypt_vectors_masterkey.yml create mode 100644 codebuild/py38/decrypt_dafny_esdk_vectors.yml create mode 100644 codebuild/py38/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py38/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py38/decrypt_net_401_vectors.yml create mode 100644 codebuild/py38/encrypt_masterkey.yml create mode 100644 codebuild/py38/generate_decrypt_vectors_masterkey.yml create mode 100644 codebuild/py39/decrypt_dafny_esdk_vectors.yml create mode 100644 codebuild/py39/decrypt_masterkey_with_js.yml create mode 100644 codebuild/py39/decrypt_masterkey_with_masterkey.yml create mode 100644 codebuild/py39/decrypt_net_401_vectors.yml create mode 100644 codebuild/py39/encrypt_masterkey.yml create mode 100644 codebuild/py39/generate_decrypt_vectors_masterkey.yml create mode 100644 test_vector_handlers/requirements_mpl.txt create mode 100644 test_vector_handlers/src/awses_test_vectors/internal/mpl/__init__.py create mode 100644 test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py create mode 100644 test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py create mode 100644 test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py diff --git a/buildspec.yml b/buildspec.yml index 5dbd3f2b8..873e5941e 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -2,7 +2,9 @@ version: 0.2 batch: fast-fail: false - build-list: + build-graph: + + # 3.7 - identifier: py37_integ buildspec: codebuild/py37/integ.yml env: @@ -11,11 +13,36 @@ batch: buildspec: codebuild/py37/examples.yml env: image: aws/codebuild/standard:5.0 - - identifier: py37_awses_local - buildspec: codebuild/py37/awses_local.yml + - identifier: py37_decrypt_dafny_esdk_vectors + buildspec: codebuild/py37/decrypt_dafny_esdk_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py37_decrypt_net_401_vectors + buildspec: codebuild/py37/decrypt_net_401_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py37_encrypt_masterkey + buildspec: codebuild/py37/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py37_generate_decrypt_vectors_masterkey + buildspec: codebuild/py37/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py37_decrypt_masterkey_with_masterkey + depend-on: + - py37_generate_decrypt_vectors_masterkey + buildspec: codebuild/py37/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py37_decrypt_masterkey_with_js + depend-on: + - py37_generate_decrypt_vectors_masterkey + buildspec: codebuild/py37/decrypt_masterkey_with_js.yml env: image: aws/codebuild/standard:5.0 + # 3.8 - identifier: py38_integ buildspec: codebuild/py38/integ.yml env: @@ -24,11 +51,36 @@ batch: buildspec: codebuild/py38/examples.yml env: image: aws/codebuild/standard:5.0 - - identifier: py38_awses_local - buildspec: codebuild/py38/awses_local.yml + - identifier: py38_decrypt_dafny_esdk_vectors + buildspec: codebuild/py38/decrypt_dafny_esdk_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py38_decrypt_net_401_vectors + buildspec: codebuild/py38/decrypt_net_401_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py38_encrypt_masterkey + buildspec: codebuild/py38/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py38_generate_decrypt_vectors_masterkey + buildspec: codebuild/py38/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py38_decrypt_masterkey_with_masterkey + depend-on: + - py38_generate_decrypt_vectors_masterkey + buildspec: codebuild/py38/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py38_decrypt_masterkey_with_js + depend-on: + - py38_generate_decrypt_vectors_masterkey + buildspec: codebuild/py38/decrypt_masterkey_with_js.yml env: image: aws/codebuild/standard:5.0 + # 3.9 - identifier: py39_integ buildspec: codebuild/py39/integ.yml env: @@ -37,10 +89,36 @@ batch: buildspec: codebuild/py39/examples.yml env: image: aws/codebuild/standard:5.0 - - identifier: py39_awses_latest + - identifier: py39_decrypt_dafny_esdk_vectors + buildspec: codebuild/py39/decrypt_dafny_esdk_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py39_decrypt_net_401_vectors + buildspec: codebuild/py39/decrypt_net_401_vectors.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py39_encrypt_masterkey + buildspec: codebuild/py39/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py39_generate_decrypt_vectors_masterkey + buildspec: codebuild/py39/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py39_decrypt_masterkey_with_masterkey + depend-on: + - py39_generate_decrypt_vectors_masterkey + buildspec: codebuild/py39/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:5.0 + - identifier: py39_decrypt_masterkey_with_js + depend-on: + - py39_generate_decrypt_vectors_masterkey + buildspec: codebuild/py39/decrypt_masterkey_with_js.yml env: image: aws/codebuild/standard:5.0 + # 3.10 - identifier: py310_integ buildspec: codebuild/py310/integ.yml env: @@ -49,8 +127,32 @@ batch: buildspec: codebuild/py310/examples.yml env: image: aws/codebuild/standard:6.0 - - identifier: py310_awses_latest - buildspec: codebuild/py310/awses_local.yml + - identifier: py310_decrypt_dafny_esdk_vectors + buildspec: codebuild/py310/decrypt_dafny_esdk_vectors.yml + env: + image: aws/codebuild/standard:6.0 + - identifier: py310_decrypt_net_401_vectors + buildspec: codebuild/py310/decrypt_net_401_vectors.yml + env: + image: aws/codebuild/standard:6.0 + - identifier: py310_encrypt_masterkey + buildspec: codebuild/py310/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:6.0 + - identifier: py310_generate_decrypt_vectors_masterkey + buildspec: codebuild/py310/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:6.0 + - identifier: py310_decrypt_masterkey_with_masterkey + depend-on: + - py310_generate_decrypt_vectors_masterkey + buildspec: codebuild/py310/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:6.0 + - identifier: py310_decrypt_masterkey_with_js + depend-on: + - py310_generate_decrypt_vectors_masterkey + buildspec: codebuild/py310/decrypt_masterkey_with_js.yml env: image: aws/codebuild/standard:6.0 @@ -70,14 +172,75 @@ batch: buildspec: codebuild/py311/examples_mpl.yml env: image: aws/codebuild/standard:7.0 - - identifier: py311_awses_latest - buildspec: codebuild/py311/awses_local.yml + - identifier: py311_decrypt_dafny_esdk_vectors_masterkey + buildspec: codebuild/py311/decrypt_dafny_esdk_vectors_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_dafny_esdk_vectors_keyrings + buildspec: codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_net_401_vectors_masterkey + buildspec: codebuild/py311/decrypt_net_401_vectors_masterkey.yml env: image: aws/codebuild/standard:7.0 - - identifier: py311_awses_latest_mpl - buildspec: codebuild/py311/awses_local_mpl.yml + - identifier: py311_decrypt_net_401_vectors_keyrings + buildspec: codebuild/py311/decrypt_net_401_vectors_keyrings.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_encrypt_masterkey + buildspec: codebuild/py311/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_encrypt_keyrings + buildspec: codebuild/py311/encrypt_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_generate_decrypt_vectors_masterkey + buildspec: codebuild/py311/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_masterkey_with_masterkey + depend-on: + - py311_generate_decrypt_vectors_masterkey + buildspec: codebuild/py311/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_masterkey_with_keyrings + depend-on: + - py311_generate_decrypt_vectors_masterkey + buildspec: codebuild/py311/decrypt_masterkey_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_masterkey_with_js + depend-on: + - py311_generate_decrypt_vectors_masterkey + buildspec: codebuild/py311/decrypt_masterkey_with_js.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_generate_decrypt_vectors_keyrings + buildspec: codebuild/py311/generate_decrypt_vectors_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_keyrings_with_masterkey + depend-on: + - py311_generate_decrypt_vectors_keyrings + buildspec: codebuild/py311/decrypt_keyrings_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_keyrings_with_keyrings + depend-on: + - py311_generate_decrypt_vectors_keyrings + buildspec: codebuild/py311/decrypt_keyrings_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_keyrings_with_js + depend-on: + - py311_generate_decrypt_vectors_keyrings + buildspec: codebuild/py311/decrypt_keyrings_with_js.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_integ buildspec: codebuild/py312/integ.yml @@ -95,15 +258,76 @@ batch: buildspec: codebuild/py312/examples_mpl.yml env: image: aws/codebuild/standard:7.0 - - identifier: py312_awses_latest - buildspec: codebuild/py312/awses_local.yml + - identifier: py312_decrypt_dafny_esdk_vectors_masterkey + buildspec: codebuild/py312/decrypt_dafny_esdk_vectors_masterkey.yml env: image: aws/codebuild/standard:7.0 - - identifier: py312_awses_latest_mpl - buildspec: codebuild/py312/awses_local_mpl.yml + - identifier: py312_decrypt_dafny_esdk_vectors_keyrings + buildspec: codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml env: image: aws/codebuild/standard:7.0 - + - identifier: py312_decrypt_net_401_vectors_masterkey + buildspec: codebuild/py312/decrypt_net_401_vectors_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_net_401_vectors_keyrings + buildspec: codebuild/py312/decrypt_net_401_vectors_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_encrypt_masterkey + buildspec: codebuild/py312/encrypt_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_encrypt_keyrings + buildspec: codebuild/py312/encrypt_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_generate_decrypt_vectors_masterkey + buildspec: codebuild/py312/generate_decrypt_vectors_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_masterkey_with_masterkey + depend-on: + - py312_generate_decrypt_vectors_masterkey + buildspec: codebuild/py312/decrypt_masterkey_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_masterkey_with_keyrings + depend-on: + - py312_generate_decrypt_vectors_masterkey + buildspec: codebuild/py312/decrypt_masterkey_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_masterkey_with_js + depend-on: + - py312_generate_decrypt_vectors_masterkey + buildspec: codebuild/py312/decrypt_masterkey_with_js.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_generate_decrypt_vectors_keyrings + buildspec: codebuild/py312/generate_decrypt_vectors_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_keyrings_with_masterkey + depend-on: + - py312_generate_decrypt_vectors_keyrings + buildspec: codebuild/py312/decrypt_keyrings_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_keyrings_with_keyrings + depend-on: + - py312_generate_decrypt_vectors_keyrings + buildspec: codebuild/py312/decrypt_keyrings_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_keyrings_with_js + depend-on: + - py312_generate_decrypt_vectors_keyrings + buildspec: codebuild/py312/decrypt_keyrings_with_js.yml + env: + image: aws/codebuild/standard:7.0 + + - identifier: code_coverage buildspec: codebuild/coverage/coverage.yml - identifier: code_coverage_mpl diff --git a/codebuild/py310/decrypt_dafny_esdk_vectors.yml b/codebuild/py310/decrypt_dafny_esdk_vectors.yml new file mode 100644 index 000000000..505f3157c --- /dev/null +++ b/codebuild/py310/decrypt_dafny_esdk_vectors.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py310-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.10 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py310/decrypt_masterkey_with_js.yml b/codebuild/py310/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..fdfb2363c --- /dev/null +++ b/codebuild/py310/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.10 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/310_masterkey.zip 310_masterkey.zip + # Repackage zip in expected format + - unzip 310_masterkey.zip + - cd 310_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py310/decrypt_masterkey_with_masterkey.yml b/codebuild/py310/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..577e81b9a --- /dev/null +++ b/codebuild/py310/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py310-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.10 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/310_masterkey.zip 310_masterkey.zip + - unzip 310_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../310_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py310/decrypt_net_401_vectors.yml b/codebuild/py310/decrypt_net_401_vectors.yml new file mode 100644 index 000000000..82ac642d9 --- /dev/null +++ b/codebuild/py310/decrypt_net_401_vectors.yml @@ -0,0 +1,35 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py310-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.10 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json diff --git a/codebuild/py310/encrypt_masterkey.yml b/codebuild/py310/encrypt_masterkey.yml new file mode 100644 index 000000000..9cd89fb8f --- /dev/null +++ b/codebuild/py310/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py310-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.10 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py310/generate_decrypt_vectors_masterkey.yml b/codebuild/py310/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..640fb72d6 --- /dev/null +++ b/codebuild/py310/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py310-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.10 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 310_masterkey + - zip -r 310_masterkey.zip 310_masterkey + - aws s3 cp 310_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/310_masterkey.zip diff --git a/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml new file mode 100644 index 000000000..d69ce9370 --- /dev/null +++ b/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml @@ -0,0 +1,59 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json \ + --keyrings diff --git a/codebuild/py311/decrypt_dafny_esdk_vectors_masterkey.yml b/codebuild/py311/decrypt_dafny_esdk_vectors_masterkey.yml new file mode 100644 index 000000000..6106906b5 --- /dev/null +++ b/codebuild/py311/decrypt_dafny_esdk_vectors_masterkey.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py311-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py311/decrypt_keyrings_with_js.yml b/codebuild/py311/decrypt_keyrings_with_js.yml new file mode 100644 index 000000000..578b83cab --- /dev/null +++ b/codebuild/py311/decrypt_keyrings_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_keyrings.zip 311_keyrings.zip + # Repackage zip in expected format + - unzip 311_keyrings.zip + - cd 311_keyrings + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py311/decrypt_keyrings_with_keyrings.yml b/codebuild/py311/decrypt_keyrings_with_keyrings.yml new file mode 100644 index 000000000..fec275d48 --- /dev/null +++ b/codebuild/py311/decrypt_keyrings_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_keyrings.zip 311_keyrings.zip + - unzip 311_keyrings.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../311_keyrings/manifest.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py311/decrypt_keyrings_with_masterkey.yml b/codebuild/py311/decrypt_keyrings_with_masterkey.yml new file mode 100644 index 000000000..714882c54 --- /dev/null +++ b/codebuild/py311/decrypt_keyrings_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_keyrings.zip 311_keyrings.zip + - unzip 311_keyrings.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../311_keyrings/manifest.json \ No newline at end of file diff --git a/codebuild/py311/decrypt_masterkey_with_js.yml b/codebuild/py311/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..a73e93580 --- /dev/null +++ b/codebuild/py311/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_masterkey.zip 311_masterkey.zip + # Repackage zip in expected format + - unzip 311_masterkey.zip + - cd 311_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py311/decrypt_masterkey_with_keyrings.yml b/codebuild/py311/decrypt_masterkey_with_keyrings.yml new file mode 100644 index 000000000..8543077bd --- /dev/null +++ b/codebuild/py311/decrypt_masterkey_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_masterkey.zip 311_masterkey.zip + - unzip 311_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../311_masterkey/manifest.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py311/decrypt_masterkey_with_masterkey.yml b/codebuild/py311/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..dd64d2dff --- /dev/null +++ b/codebuild/py311/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_masterkey.zip 311_masterkey.zip + - unzip 311_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../311_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py311/decrypt_net_401_vectors_keyrings.yml b/codebuild/py311/decrypt_net_401_vectors_keyrings.yml new file mode 100644 index 000000000..1a23f0917 --- /dev/null +++ b/codebuild/py311/decrypt_net_401_vectors_keyrings.yml @@ -0,0 +1,36 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json \ + --keyrings diff --git a/codebuild/py311/decrypt_net_401_vectors_masterkey.yml b/codebuild/py311/decrypt_net_401_vectors_masterkey.yml new file mode 100644 index 000000000..f6f0482e7 --- /dev/null +++ b/codebuild/py311/decrypt_net_401_vectors_masterkey.yml @@ -0,0 +1,45 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py311-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_API_DEPLOYMENT_ID: "xi1mwx3ttb" + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_REGION: "us-west-2" + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Assume Role to access non-prod resources + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-TestVectorResources") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json \ No newline at end of file diff --git a/codebuild/py311/encrypt_keyrings.yml b/codebuild/py311/encrypt_keyrings.yml new file mode 100644 index 000000000..8b7cb94b4 --- /dev/null +++ b/codebuild/py311/encrypt_keyrings.yml @@ -0,0 +1,26 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_encrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py311/encrypt_masterkey.yml b/codebuild/py311/encrypt_masterkey.yml new file mode 100644 index 000000000..226e1586d --- /dev/null +++ b/codebuild/py311/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py311/generate_decrypt_vectors_keyrings.yml b/codebuild/py311/generate_decrypt_vectors_keyrings.yml new file mode 100644 index 000000000..179ec0f12 --- /dev/null +++ b/codebuild/py311/generate_decrypt_vectors_keyrings.yml @@ -0,0 +1,29 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt_generate-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 311_keyrings \ + --keyrings + - zip -r 311_keyrings.zip 311_keyrings + - aws s3 cp 311_keyrings.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_keyrings.zip diff --git a/codebuild/py311/generate_decrypt_vectors_masterkey.yml b/codebuild/py311/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..84db3f176 --- /dev/null +++ b/codebuild/py311/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 311_masterkey + - zip -r 311_masterkey.zip 311_masterkey + - aws s3 cp 311_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_masterkey.zip diff --git a/codebuild/py312/awses_local.yml b/codebuild/py312/awses_local.yml index 0a81984ee..844cc7993 100644 --- a/codebuild/py312/awses_local.yml +++ b/codebuild/py312/awses_local.yml @@ -17,14 +17,9 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - - - pyenv install --skip-existing 3.12.0 - - pyenv local 3.12.0 - - pip install --upgrade pip - - pip install setuptools - pip install "tox < 4.0" - cd test_vector_handlers - tox diff --git a/codebuild/py312/awses_local_mpl.yml b/codebuild/py312/awses_local_mpl.yml index 1d0f80319..c92265541 100644 --- a/codebuild/py312/awses_local_mpl.yml +++ b/codebuild/py312/awses_local_mpl.yml @@ -20,7 +20,7 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml new file mode 100644 index 000000000..810d16b74 --- /dev/null +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -0,0 +1,59 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json \ + --keyrings diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_masterkey.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_masterkey.yml new file mode 100644 index 000000000..b375651c5 --- /dev/null +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_masterkey.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py312-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py312/decrypt_keyrings_with_js.yml b/codebuild/py312/decrypt_keyrings_with_js.yml new file mode 100644 index 000000000..9b1ebc270 --- /dev/null +++ b/codebuild/py312/decrypt_keyrings_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_keyrings.zip 312_keyrings.zip + # Repackage zip in expected format + - unzip 312_keyrings.zip + - cd 312_keyrings + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py312/decrypt_keyrings_with_keyrings.yml b/codebuild/py312/decrypt_keyrings_with_keyrings.yml new file mode 100644 index 000000000..3ab7058f9 --- /dev/null +++ b/codebuild/py312/decrypt_keyrings_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_keyrings.zip 312_keyrings.zip + - unzip 312_keyrings.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_keyrings/manifest.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py312/decrypt_keyrings_with_masterkey.yml b/codebuild/py312/decrypt_keyrings_with_masterkey.yml new file mode 100644 index 000000000..bb06ba4a2 --- /dev/null +++ b/codebuild/py312/decrypt_keyrings_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_keyrings.zip 312_keyrings.zip + - unzip 312_keyrings.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_keyrings/manifest.json \ No newline at end of file diff --git a/codebuild/py312/decrypt_masterkey_with_js.yml b/codebuild/py312/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..7c57c3111 --- /dev/null +++ b/codebuild/py312/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_masterkey.zip 312_masterkey.zip + # Repackage zip in expected format + - unzip 312_masterkey.zip + - cd 312_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py312/decrypt_masterkey_with_keyrings.yml b/codebuild/py312/decrypt_masterkey_with_keyrings.yml new file mode 100644 index 000000000..21f646370 --- /dev/null +++ b/codebuild/py312/decrypt_masterkey_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_masterkey.zip 312_masterkey.zip + - unzip 312_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_masterkey/manifest.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py312/decrypt_masterkey_with_masterkey.yml b/codebuild/py312/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..0529fd894 --- /dev/null +++ b/codebuild/py312/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_masterkey.zip 312_masterkey.zip + - unzip 312_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py312/decrypt_net_401_vectors_keyrings.yml b/codebuild/py312/decrypt_net_401_vectors_keyrings.yml new file mode 100644 index 000000000..aec3916e5 --- /dev/null +++ b/codebuild/py312/decrypt_net_401_vectors_keyrings.yml @@ -0,0 +1,36 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json \ + --keyrings diff --git a/codebuild/py312/decrypt_net_401_vectors_masterkey.yml b/codebuild/py312/decrypt_net_401_vectors_masterkey.yml new file mode 100644 index 000000000..5d1ef9d94 --- /dev/null +++ b/codebuild/py312/decrypt_net_401_vectors_masterkey.yml @@ -0,0 +1,45 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py312-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_API_DEPLOYMENT_ID: "xi1mwx3ttb" + AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_REGION: "us-west-2" + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Assume Role to access non-prod resources + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-TestVectorResources") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json \ No newline at end of file diff --git a/codebuild/py312/encrypt_keyrings.yml b/codebuild/py312/encrypt_keyrings.yml new file mode 100644 index 000000000..56a389e6f --- /dev/null +++ b/codebuild/py312/encrypt_keyrings.yml @@ -0,0 +1,26 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_encrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py312/encrypt_masterkey.yml b/codebuild/py312/encrypt_masterkey.yml new file mode 100644 index 000000000..940f336a2 --- /dev/null +++ b/codebuild/py312/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py312/examples.yml b/codebuild/py312/examples.yml index 691ea0e60..855a8fcdb 100644 --- a/codebuild/py312/examples.yml +++ b/codebuild/py312/examples.yml @@ -15,13 +15,8 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - - - pyenv install --skip-existing 3.12.0 - - pyenv local 3.12.0 - - pip install --upgrade pip - - pip install setuptools - pip install "tox < 4.0" - tox diff --git a/codebuild/py312/examples_mpl.yml b/codebuild/py312/examples_mpl.yml index 366222441..bca624742 100644 --- a/codebuild/py312/examples_mpl.yml +++ b/codebuild/py312/examples_mpl.yml @@ -19,7 +19,7 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - @@ -31,7 +31,7 @@ phases: # Run non-MPL-specific tests with the MPL installed - tox -e py312-examples-mpl # Assume special role to access keystore - - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py311ExamplesMpl") + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl") - export TMP_ROLE - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') diff --git a/codebuild/py312/generate_decrypt_vectors_keyrings.yml b/codebuild/py312/generate_decrypt_vectors_keyrings.yml new file mode 100644 index 000000000..ae79b86ce --- /dev/null +++ b/codebuild/py312/generate_decrypt_vectors_keyrings.yml @@ -0,0 +1,29 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt_generate-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 312_keyrings \ + --keyrings + - zip -r 312_keyrings.zip 312_keyrings + - aws s3 cp 312_keyrings.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_keyrings.zip diff --git a/codebuild/py312/generate_decrypt_vectors_masterkey.yml b/codebuild/py312/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..1fadba985 --- /dev/null +++ b/codebuild/py312/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 312_masterkey + - zip -r 312_masterkey.zip 312_masterkey + - aws s3 cp 312_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_masterkey.zip diff --git a/codebuild/py312/integ.yml b/codebuild/py312/integ.yml index 10899f1df..2ccad8913 100644 --- a/codebuild/py312/integ.yml +++ b/codebuild/py312/integ.yml @@ -15,13 +15,8 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - - - pyenv install --skip-existing 3.12.0 - - pyenv local 3.12.0 - - pip install --upgrade pip - - pip install setuptools - pip install "tox < 4.0" - tox diff --git a/codebuild/py312/integ_mpl.yml b/codebuild/py312/integ_mpl.yml index e292acc57..7c6f046fe 100644 --- a/codebuild/py312/integ_mpl.yml +++ b/codebuild/py312/integ_mpl.yml @@ -18,7 +18,7 @@ env: phases: install: runtime-versions: - python: latest + python: 3.12 build: commands: - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - diff --git a/codebuild/py37/decrypt_dafny_esdk_vectors.yml b/codebuild/py37/decrypt_dafny_esdk_vectors.yml new file mode 100644 index 000000000..ee2d428c7 --- /dev/null +++ b/codebuild/py37/decrypt_dafny_esdk_vectors.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py37-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.7 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py37/decrypt_masterkey_with_js.yml b/codebuild/py37/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..8a44e11e7 --- /dev/null +++ b/codebuild/py37/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.7 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip 37_masterkey.zip + # Repackage zip in expected format + - unzip 37_masterkey.zip + - cd 37_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py37/decrypt_masterkey_with_masterkey.yml b/codebuild/py37/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..1774b05f4 --- /dev/null +++ b/codebuild/py37/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py37-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.7 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip 37_masterkey.zip + - unzip 37_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../37_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py37/decrypt_net_401_vectors.yml b/codebuild/py37/decrypt_net_401_vectors.yml new file mode 100644 index 000000000..1dfb48ce8 --- /dev/null +++ b/codebuild/py37/decrypt_net_401_vectors.yml @@ -0,0 +1,35 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py37-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.7 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json diff --git a/codebuild/py37/encrypt_masterkey.yml b/codebuild/py37/encrypt_masterkey.yml new file mode 100644 index 000000000..7cdc7848e --- /dev/null +++ b/codebuild/py37/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py37-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.7 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py37/generate_decrypt_vectors_masterkey.yml b/codebuild/py37/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..55ec3e9e4 --- /dev/null +++ b/codebuild/py37/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py37-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.7 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 37_masterkey + - zip -r 37_masterkey.zip 37_masterkey + - aws s3 cp 37_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip diff --git a/codebuild/py38/decrypt_dafny_esdk_vectors.yml b/codebuild/py38/decrypt_dafny_esdk_vectors.yml new file mode 100644 index 000000000..968a74690 --- /dev/null +++ b/codebuild/py38/decrypt_dafny_esdk_vectors.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py38-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.8 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py38/decrypt_masterkey_with_js.yml b/codebuild/py38/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..953e8818a --- /dev/null +++ b/codebuild/py38/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.8 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/38_masterkey.zip 38_masterkey.zip + # Repackage zip in expected format + - unzip 38_masterkey.zip + - cd 38_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py38/decrypt_masterkey_with_masterkey.yml b/codebuild/py38/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..6b32dcf15 --- /dev/null +++ b/codebuild/py38/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py38-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.8 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/38_masterkey.zip 38_masterkey.zip + - unzip 38_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../38_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py38/decrypt_net_401_vectors.yml b/codebuild/py38/decrypt_net_401_vectors.yml new file mode 100644 index 000000000..298711975 --- /dev/null +++ b/codebuild/py38/decrypt_net_401_vectors.yml @@ -0,0 +1,35 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py38-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.8 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json diff --git a/codebuild/py38/encrypt_masterkey.yml b/codebuild/py38/encrypt_masterkey.yml new file mode 100644 index 000000000..b05396cc2 --- /dev/null +++ b/codebuild/py38/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py38-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.8 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py38/generate_decrypt_vectors_masterkey.yml b/codebuild/py38/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..8705ef57c --- /dev/null +++ b/codebuild/py38/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py38-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.8 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 38_masterkey + - zip -r 38_masterkey.zip 38_masterkey + - aws s3 cp 38_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/38_masterkey.zip diff --git a/codebuild/py39/decrypt_dafny_esdk_vectors.yml b/codebuild/py39/decrypt_dafny_esdk_vectors.yml new file mode 100644 index 000000000..ddb50db1c --- /dev/null +++ b/codebuild/py39/decrypt_dafny_esdk_vectors.yml @@ -0,0 +1,58 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py39-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + git-credential-helper: yes + secrets-manager: + GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read + +phases: + install: + runtime-versions: + python: 3.9 + pre_build: + commands: + # Fetch test vectors from Dafny ESDK's most recent run + # (Assuming the first result is most recent; seems to be correct...) + - | + MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ + | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') + - | + echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" + - | + MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ + | jq '.artifacts[0].archive_download_url') + - | + echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" + - | + curl -L -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip + # This unzips to `net41.zip`. + - unzip ubuntu-latest_test_vector_artifact + # This unzips to `net41/`. + - unzip net41.zip -d net41 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../net41/manifest.json diff --git a/codebuild/py39/decrypt_masterkey_with_js.yml b/codebuild/py39/decrypt_masterkey_with_js.yml new file mode 100644 index 000000000..53f6433f8 --- /dev/null +++ b/codebuild/py39/decrypt_masterkey_with_js.yml @@ -0,0 +1,34 @@ +version: 0.2 + +env: + variables: + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.9 + commands: + - n 16 + # Install the Javascript ESDK run test vectors + - npm install -g @aws-crypto/integration-node + + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/39_masterkey.zip 39_masterkey.zip + # Repackage zip in expected format + - unzip 39_masterkey.zip + - cd 39_masterkey + - zip -r vectors.zip . + build: + commands: + # Decrypt generated vectors with Javascript ESDK + - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py39/decrypt_masterkey_with_masterkey.yml b/codebuild/py39/decrypt_masterkey_with_masterkey.yml new file mode 100644 index 000000000..fcd9d3220 --- /dev/null +++ b/codebuild/py39/decrypt_masterkey_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py39-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.9 + pre_build: + commands: + # Download previously generated vectors + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/39_masterkey.zip 39_masterkey.zip + - unzip 39_masterkey.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../39_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py39/decrypt_net_401_vectors.yml b/codebuild/py39/decrypt_net_401_vectors.yml new file mode 100644 index 000000000..635abc95b --- /dev/null +++ b/codebuild/py39/decrypt_net_401_vectors.yml @@ -0,0 +1,35 @@ +version: 0.2 +# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM + +env: + variables: + TOXENV: "py39-full_decrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.9 + pre_build: + commands: + # Fetch ESDK .NET v4.0.1 Test Vectors + - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip + - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip + - curl -s --output $VECTOR_ZIP --location $VECTORS_URL + - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors + - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR + build: + commands: + # NOTE: We need to pass the absolute path of the vectors + - pip install "tox < 4.0" + - cd $CODEBUILD_SRC_DIR/test_vector_handlers + - | + tox -- \ + --input $UNZIPPED_VECTORS_DIR/manifest.json diff --git a/codebuild/py39/encrypt_masterkey.yml b/codebuild/py39/encrypt_masterkey.yml new file mode 100644 index 000000000..3bf18fbde --- /dev/null +++ b/codebuild/py39/encrypt_masterkey.yml @@ -0,0 +1,25 @@ +version: 0.2 + +env: + variables: + TOXENV: "py39-full_encrypt" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.9 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py39/generate_decrypt_vectors_masterkey.yml b/codebuild/py39/generate_decrypt_vectors_masterkey.yml new file mode 100644 index 000000000..eb57d915a --- /dev/null +++ b/codebuild/py39/generate_decrypt_vectors_masterkey.yml @@ -0,0 +1,28 @@ +version: 0.2 + +env: + variables: + TOXENV: "py39-full_decrypt_generate" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.9 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ + --output 39_masterkey + - zip -r 39_masterkey.zip 39_masterkey + - aws s3 cp 39_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/39_masterkey.zip diff --git a/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py b/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py index 91f9fd834..da9bc9b6b 100644 --- a/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py +++ b/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py @@ -98,9 +98,12 @@ def decrypt(self, encrypted_wrapped_data_key, encryption_context): if self.wrapping_key_type is EncryptionKeyType.PUBLIC: raise IncorrectMasterKeyError("Public key cannot decrypt") if self.wrapping_key_type is EncryptionKeyType.PRIVATE: - return self._wrapping_key.decrypt( - ciphertext=encrypted_wrapped_data_key.ciphertext, padding=self.wrapping_algorithm.padding - ) + try: + return self._wrapping_key.decrypt( + ciphertext=encrypted_wrapped_data_key.ciphertext, padding=self.wrapping_algorithm.padding + ) + except ValueError: + raise IncorrectMasterKeyError("_wrapping_key cannot decrypt provided ciphertext") serialized_encryption_context = serialize_encryption_context(encryption_context=encryption_context) return decrypt( algorithm=self.wrapping_algorithm.algorithm, diff --git a/src/aws_encryption_sdk/internal/formatting/deserialize.py b/src/aws_encryption_sdk/internal/formatting/deserialize.py index b06b5ba11..1b46a8b7d 100644 --- a/src/aws_encryption_sdk/internal/formatting/deserialize.py +++ b/src/aws_encryption_sdk/internal/formatting/deserialize.py @@ -475,7 +475,7 @@ def deserialize_frame(stream, header, verifier=None): frame_data["iv"] = frame_iv if final_frame is True: (content_length,) = unpack_values(">I", stream, verifier) - if content_length >= header.frame_length: + if content_length > header.frame_length: raise SerializationError( "Invalid final frame length: {final} >= {normal}".format( final=content_length, normal=header.frame_length diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt new file mode 100644 index 000000000..c7927a851 --- /dev/null +++ b/test_vector_handlers/requirements_mpl.txt @@ -0,0 +1 @@ +amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py index baf1d1f03..2a44cd597 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py @@ -15,6 +15,13 @@ from awses_test_vectors.manifests.full_message.decrypt import MessageDecryptionManifest +try: + import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + + try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable, Optional # noqa pylint: disable=unused-import except ImportError: # pragma: no cover @@ -29,9 +36,19 @@ def cli(args=None): parser.add_argument( "--input", required=True, type=argparse.FileType("r"), help="Existing full message decrypt manifest" ) + parser.add_argument( + "--keyrings", + action="store_true", + required=False, + default=False, + help="Use keyring interfaces to encrypt", + ) parsed = parser.parse_args(args) - decrypt_manifest = MessageDecryptionManifest.from_file(parsed.input) + if parsed.keyrings and not _HAS_MPL: + raise ImportError("The --keyrings flag requires the aws-cryptographic-material-providers library.") + + decrypt_manifest = MessageDecryptionManifest.from_file(parsed.input, parsed.keyrings) decrypt_manifest.run() diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py index 5d8b94893..69fe44d78 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py @@ -15,6 +15,12 @@ from awses_test_vectors.manifests.full_message.decrypt_generation import MessageDecryptionGenerationManifest +try: + import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable, Optional # noqa pylint: disable=unused-import except ImportError: # pragma: no cover @@ -39,9 +45,19 @@ def cli(args=None): dest="json_indent", help="Output human-readable JSON", ) + parser.add_argument( + "--keyrings", + action="store_true", + required=False, + default=False, + help="Use keyring interfaces to encrypt", + ) parsed = parser.parse_args(args) - encrypt_manifest = MessageDecryptionGenerationManifest.from_file(parsed.input) + if parsed.keyrings and not _HAS_MPL: + raise ImportError("The --keyrings flag requires the aws-cryptographic-material-providers library.") + + encrypt_manifest = MessageDecryptionGenerationManifest.from_file(parsed.input, parsed.keyrings) encrypt_manifest.run_and_write_to_dir(target_directory=parsed.output, json_indent=parsed.json_indent) diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py index 2b8b92f3c..268d7ca99 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py @@ -15,6 +15,13 @@ from awses_test_vectors.manifests.full_message.encrypt import MessageEncryptionManifest +try: + import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + + try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable, Optional # noqa pylint: disable=unused-import except ImportError: # pragma: no cover @@ -29,9 +36,19 @@ def cli(args=None): parser.add_argument( "--input", required=True, type=argparse.FileType("r"), help="Existing full message encrypt manifest" ) + parser.add_argument( + "--keyrings", + action="store_true", + required=False, + default=False, + help="Use keyring interfaces to encrypt", + ) parsed = parser.parse_args(args) - encrypt_manifest = MessageEncryptionManifest.from_file(parsed.input) + if parsed.keyrings and not _HAS_MPL: + raise ImportError("The --keyrings flag requires the aws-cryptographic-material-providers library.") + + encrypt_manifest = MessageEncryptionManifest.from_file(parsed.input, parsed.keyrings) encrypt_manifest.run() diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mpl/__init__.py b/test_vector_handlers/src/awses_test_vectors/internal/mpl/__init__.py new file mode 100644 index 000000000..11e9569d9 --- /dev/null +++ b/test_vector_handlers/src/awses_test_vectors/internal/mpl/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Internal modules that require the aws-cryptographic-material-providers library.""" diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py b/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py new file mode 100644 index 000000000..305459026 --- /dev/null +++ b/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py @@ -0,0 +1,27 @@ +"""Singleton provider for the KeyVectors client.""" +# # Ignore missing MPL TestVectors for pylint, but the MPL TestVectors is required for this file +# pylint: disable=import-error +from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ + aws_cryptography_materialproviderstestvectorkeys.client import ( + KeyVectors, + ) +from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ + aws_cryptography_materialproviderstestvectorkeys.config import ( + KeyVectorsConfig + ) + +keyvectors_instances = {} + + +# pylint: disable=too-few-public-methods +class KeyVectorsProvider: + """Singleton manager for the KeyVectors client.""" + + instance: KeyVectors + + @classmethod + def get_keyvectors(cls, keys_path): + """Return the singleton KeyVectors client.""" + if keys_path not in keyvectors_instances: + keyvectors_instances[keys_path] = KeyVectors(KeyVectorsConfig(key_manifest_path=keys_path)) + return keyvectors_instances[keys_path] diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py b/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py new file mode 100644 index 000000000..29a820ecc --- /dev/null +++ b/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py @@ -0,0 +1,179 @@ +"""Allows using ESDK-MPL interfaces with the tampering tests. +These must ONLY be used in testing and NOT in production. +""" +from copy import copy +import attr +import six + + +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager + +# Ignore missing MPL for pylint, but the MPL is required for this class +# pylint: disable=import-error,no-name-in-module +from aws_encryption_sdk.materials_managers.mpl.materials import ( + EncryptionMaterialsFromMPL +) +from aws_encryption_sdk.materials_managers.mpl.cmm import ( + CryptoMaterialsManagerFromMPL +) +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, +) + +try: + from aws_encryption_sdk.identifiers import AlgorithmSuite +except ImportError: + from aws_encryption_sdk.identifiers import Algorithm as AlgorithmSuite + + +class HalfSigningCryptoMaterialsManagerFromMPL(CryptoMaterialsManagerFromMPL): + """ + Custom CMM that uses HalfSigningEncryptionMaterialsFromMPL. + This extends CryptoMaterialsManagerFromMPL so ESDK-internal checks + follow MPL logic. + + THIS IS ONLY USED TO CREATE INVALID MESSAGES and should never be used in + production! + """ + + wrapped_default_cmm = attr.ib(validator=attr.validators.instance_of(CryptoMaterialsManagerFromMPL)) + + def __init__(self, master_key_provider): + """Create a new CMM that wraps a the given CMM.""" + mpl = AwsCryptographicMaterialProviders(MaterialProvidersConfig()) + mpl_cmm = mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=master_key_provider + ) + ) + self.wrapped_default_cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mpl_cmm) + + def get_encryption_materials(self, request): + """ + Generate half-signing materials by requesting signing materials + from the wrapped default CMM, and then changing the algorithm suite + and removing the signing key from teh result. + """ + if request.algorithm == AlgorithmSuite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY: + signing_request = copy(request) + signing_request.algorithm = AlgorithmSuite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 + + result = HalfSigningEncryptionMaterialsFromMPL( + self.wrapped_default_cmm.get_encryption_materials(signing_request) + ) + + result.algorithm = request.algorithm + result.signing_key = None + + return result + + raise NotImplementedError( + "The half-sign tampering method is only supported on the " + "AES_256_GCM_HKDF_SHA512_COMMIT_KEY algorithm suite." + ) + + def decrypt_materials(self, request): + """Thunks to the wrapped default CMM""" + return self.wrapped_default_cmm.decrypt_materials(request) + + +class HalfSigningEncryptionMaterialsFromMPL(EncryptionMaterialsFromMPL): + """Allows overriding properties inside the EncryptionMaterialsFromMPL. + The test vectors to this to "tamper" with the messages + and ensure they fail with expected errors. + This must ONLY be used in testing and NOT in production. + This is used in testing malicious message modification (HalfSigningTampering). + """ + + _underlying_materials: EncryptionMaterialsFromMPL + + def __init__(self, underlying_materials): + """Create a HalfSigningEncryptionMaterialsFromMPL wrapper + around underlying_materials. + """ + self._underlying_materials = underlying_materials + + # pylint thinks EncryptionMaterialsFromMPL.algorithm is a method + # pylint: disable=invalid-overridden-method + @property + def algorithm(self): + """Return any previously-provided overriden algorithm; + if none was provided, returns underlying algorithm from encryption materials. + """ + if hasattr(self, "set_algorithm"): + return self.set_algorithm + return self._underlying_materials.algorithm + + @algorithm.setter + def algorithm(self, algorithm): + self.set_algorithm = algorithm + + # pylint thinks EncryptionMaterialsFromMPL.signing_key is a method + # pylint: disable=invalid-overridden-method + @property + def signing_key(self): + """Return any previously-provided overriden signing_key; + if none was provided, returns underlying signing_key from encryption materials. + """ + if hasattr(self, "set_signing_key"): + return self.set_signing_key + return self._underlying_materials.algorithm + + @signing_key.setter + def signing_key(self, signing_key): + self.set_signing_key = signing_key + + @property + def encryption_context(self): + """Get encryption_context from _underlying_materials.""" + return self._underlying_materials.encryption_context + + @property + def encrypted_data_keys(self): + """Get encrypted_data_keys from _underlying_materials.""" + return self._underlying_materials.encrypted_data_keys + + @property + def data_encryption_key(self): + """Get data_encryption_key from _underlying_materials.""" + return self._underlying_materials.data_encryption_key + + @property + def required_encryption_context_keys(self): + """Get required_encryption_context_keys from _underlying_materials.""" + return self._underlying_materials.required_encryption_context_keys + + +class ProviderInfoChangingCryptoMaterialsManagerFromMPL(CryptoMaterialsManagerFromMPL): + """ + Custom CMM that modifies the provider info field on EDKs. + This extends CryptoMaterialsManagerFromMPL so ESDK-internal checks + follow MPL logic. + + THIS IS ONLY USED TO CREATE INVALID MESSAGES and should never be used in + production! + """ + + wrapped_cmm = attr.ib(validator=attr.validators.instance_of(CryptoMaterialsManager)) + new_provider_info = attr.ib(validator=attr.validators.instance_of(six.string_types)) + + def __init__(self, materials_manager, new_provider_info): + """Create a new CMM that wraps a the given CMM.""" + self.wrapped_cmm = materials_manager + self.new_provider_info = new_provider_info + + def get_encryption_materials(self, request): + """ + Request materials from the wrapped CMM, and then change the provider info + on each EDK. + """ + result = self.wrapped_cmm.get_encryption_materials(request) + for encrypted_data_key in result.encrypted_data_keys: + encrypted_data_key.key_provider.key_info = self.new_provider_info + return result + + def decrypt_materials(self, request): + """Thunks to the wrapped CMM""" + return self.wrapped_cmm.decrypt_materials(request) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index c94fd1452..2aaaf1bca 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -35,6 +35,21 @@ from awses_test_vectors.manifests.keys import KeysManifest from awses_test_vectors.manifests.master_key import MasterKeySpec, master_key_provider_from_master_key_specs +try: + from awses_test_vectors.manifests.mpl_keyring import KeyringSpec, keyring_from_master_key_specs + from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager + from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, + CreateRequiredEncryptionContextCMMInput, + ) + + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + + try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import IO, Callable, Dict, Iterable, Optional # noqa pylint: disable=unused-import @@ -49,7 +64,7 @@ CLIENT_NAME = "aws/aws-encryption-sdk-python" CURRENT_VERSION = 2 -SUPPORTED_VERSIONS = (2,) +SUPPORTED_VERSIONS = (2, 4,) @attr.s(init=False) @@ -181,7 +196,7 @@ class DecryptionMethod(Enum): @attr.s(init=False) class MessageDecryptionTestScenario(object): - # pylint: disable=too-many-arguments + # pylint: disable=too-many-arguments,too-many-instance-attributes """Data class for a single full message decrypt test scenario. Handles serialization and deserialization to and from manifest specs. @@ -192,6 +207,10 @@ class MessageDecryptionTestScenario(object): :param master_key_specs: Iterable of master key specifications :type master_key_specs: iterable of :class:`MasterKeySpec` :param Callable master_key_provider_fn: + :param bool keyrings: True if should decrypt with keyring interfaces; False otherwise + :param str cmm_type: `cmm` from test vector manifest; "Default" if not specified + :param str encryption_context: Any encryption context to validate on decrypt if using + keyrings AND the required encryption context CMM :param str description: Description of test scenario (optional) """ @@ -202,6 +221,8 @@ class MessageDecryptionTestScenario(object): master_key_specs = attr.ib(validator=iterable_validator(list, MasterKeySpec)) master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) result = attr.ib(validator=attr.validators.instance_of(MessageDecryptionTestResult)) + keyrings = attr.ib(validator=attr.validators.instance_of(bool)) + cmm_type = attr.ib(validator=attr.validators.instance_of(str)) decryption_method = attr.ib( default=None, validator=attr.validators.optional(attr.validators.instance_of(DecryptionMethod)) ) @@ -216,6 +237,9 @@ def __init__( result, # type: MessageDecryptionTestResult master_key_specs, # type: Iterable[MasterKeySpec] master_key_provider_fn, # type: Callable + keyrings, # type: bool + cmm_type, # type: str + encryption_context, # type: Dict[str, str] decryption_method=None, # type: Optional[DecryptionMethod] description=None, # type: Optional[str] ): # noqa=D107 @@ -229,6 +253,9 @@ def __init__( self.result = result self.master_key_specs = master_key_specs self.master_key_provider_fn = master_key_provider_fn + self.keyrings = keyrings + self.cmm_type = cmm_type + self.encryption_context = encryption_context self.decryption_method = decryption_method self.description = description attr.validate(self) @@ -240,7 +267,10 @@ def from_scenario( plaintext_reader, # type: Callable[[str], bytes] ciphertext_reader, # type: Callable[[str], bytes] keys, # type: KeysManifest + keyrings, # type: bool + keys_uri, # type: str ): + # pylint: disable=too-many-locals # type: (...) -> MessageDecryptionTestScenario """Load from a scenario specification. @@ -252,9 +282,18 @@ def from_scenario( :rtype: MessageDecryptionTestScenario """ raw_master_key_specs = scenario["master-keys"] # type: Iterable[MASTER_KEY_SPEC] - master_key_specs = [MasterKeySpec.from_scenario(spec) for spec in raw_master_key_specs] + if keyrings: + master_key_specs = [ + KeyringSpec.from_scenario(spec) for spec in raw_master_key_specs + ] + else: + master_key_specs = [ + MasterKeySpec.from_scenario(spec) for spec in raw_master_key_specs + ] def master_key_provider_fn(): + if keyrings: + return keyring_from_master_key_specs(keys_uri, master_key_specs, "decrypt") return master_key_provider_from_master_key_specs(keys, master_key_specs) decryption_method_spec = scenario.get("decryption-method") @@ -262,12 +301,39 @@ def master_key_provider_fn(): result_spec = scenario["result"] result = MessageDecryptionTestResult.from_result_spec(result_spec, plaintext_reader) + if "encryption-context" in scenario: + encryption_context = scenario["encryption-context"] + else: + encryption_context = {} + + # MPL test vectors add CMM types to the test vectors manifests + if "cmm" in scenario: + if scenario["cmm"] == "Default": + # Master keys and keyrings can handle default CMM + cmm_type = scenario["cmm"] + elif scenario["cmm"] == "RequiredEncryptionContext": + # Skip RequiredEncryptionContext CMM for master keys; + # RequiredEncryptionContext is unsupported for master keys. + # Caller logic should expect `None` to mean "no scenario". + if keyrings: + cmm_type = scenario["cmm"] + else: + return None + else: + raise ValueError("Unrecognized cmm_type: " + cmm_type) + else: + # If unspecified, set "Default" as the default + cmm_type = "Default" + return cls( ciphertext_uri=scenario["ciphertext"], ciphertext=ciphertext_reader(scenario["ciphertext"]), master_key_specs=master_key_specs, master_key_provider_fn=master_key_provider_fn, result=result, + keyrings=keyrings, + encryption_context=encryption_context, + cmm_type=cmm_type, decryption_method=decryption_method, description=scenario.get("description"), ) @@ -293,12 +359,98 @@ def scenario_spec(self): def _one_shot_decrypt(self): client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - return client.decrypt(source=self.ciphertext, key_provider=self.master_key_provider_fn()) + if self.cmm_type == "Default": + if self.keyrings: + return client.decrypt(source=self.ciphertext, keyring=self.master_key_provider_fn()) + return client.decrypt(source=self.ciphertext, key_provider=self.master_key_provider_fn()) + if self.cmm_type == "RequiredEncryptionContext": + # We need to make a custom CMM and pass it into the client + if not self.keyrings: + raise ValueError("Must provide keyrings arg to use RequiredEncryptionContext") + if not _HAS_MPL: + raise ValueError("Must install the aws-cryptographic-material-providers library" + "to use RequiredEncryptionContext") + + mpl: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + underlying_cmm: ICryptographicMaterialsManager = \ + mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=self.master_key_provider_fn() + ) + ) + + required_ec_cmm: ICryptographicMaterialsManager = \ + mpl.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + # Currently, the test vector manifest assumes these + # are the only required encryption context keys for any message. + # If this assumption changes, this logic must be augmented. + required_encryption_context_keys=["key1", "key2"], + underlying_cmm=underlying_cmm, + ) + ) + + return client.decrypt( + source=self.ciphertext, + materials_manager=required_ec_cmm, + encryption_context=self.encryption_context, + ) + + # If the cmm type was not in if/elif above, raise error + raise ValueError(f"Unrecognized cmm_type: {self.cmm_type}") def _streaming_decrypt(self): result = bytearray() client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - with client.stream(source=self.ciphertext, mode="d", key_provider=self.master_key_provider_fn()) as decryptor: + + kwargs = { + "source": self.ciphertext, + "mode": "d" + } + if self.cmm_type == "Default": + if self.keyrings: + kwargs["keyring"] = self.master_key_provider_fn() + else: + kwargs["key_provider"] = self.master_key_provider_fn() + elif self.cmm_type == "RequiredEncryptionContext": + # We need to make a custom CMM and pass it into the client + if not self.keyrings: + raise ValueError("Must provide keyrings arg to use RequiredEncryptionContext") + if not _HAS_MPL: + raise ValueError("Must install the aws-cryptographic-material-providers library" + "to use RequiredEncryptionContext") + + mpl: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + underlying_cmm: ICryptographicMaterialsManager = \ + mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=self.master_key_provider_fn() + ) + ) + + required_ec_cmm: ICryptographicMaterialsManager = \ + mpl.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + # Currently, the test vector manifest assumes these + # are the only required encryption context keys for any message. + # If this assumption changes, this logic must be augmented. + required_encryption_context_keys=["key1", "key2"], + underlying_cmm=underlying_cmm, + ) + ) + + kwargs["materials_manager"] = required_ec_cmm + kwargs["encryption_context"] = self.encryption_context + else: + raise ValueError(f"Unrecognized cmm_type: {self.cmm_type}") + + with client.stream(**kwargs) as decryptor: for chunk in decryptor: result.extend(chunk) return result, decryptor.header @@ -306,9 +458,53 @@ def _streaming_decrypt(self): def _streaming_decrypt_unsigned(self): result = bytearray() client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - with client.stream( - source=self.ciphertext, mode="decrypt-unsigned", key_provider=self.master_key_provider_fn() - ) as decryptor: + + stream_kwargs = { + "source": self.ciphertext, + "mode": "decrypt-unsigned", + } + + if self.cmm_type == "Default": + if self.keyrings: + stream_kwargs["keyring"] = self.master_key_provider_fn() + else: + stream_kwargs["key_provider"] = self.master_key_provider_fn() + elif self.cmm_type == "RequiredEncryptionContext": + # We need to make a custom CMM and pass it into the client + if not self.keyrings: + raise ValueError("Must provide keyrings arg to use RequiredEncryptionContext") + if not _HAS_MPL: + raise ValueError("Must install the aws-cryptographic-material-providers library" + "to use RequiredEncryptionContext") + + mpl: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + underlying_cmm: ICryptographicMaterialsManager = \ + mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=self.master_key_provider_fn() + ) + ) + + required_ec_cmm: ICryptographicMaterialsManager = \ + mpl.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + # Currently, the test vector manifest assumes these + # are the only required encryption context keys for any message. + # If this assumption changes, this logic must be augmented. + required_encryption_context_keys=["key1", "key2"], + underlying_cmm=underlying_cmm, + ) + ) + + stream_kwargs["materials_manager"] = required_ec_cmm + stream_kwargs["encryption_context"] = self.encryption_context + else: + raise ValueError(f"Unrecognized cmm_type: {self.cmm_type}") + + with client.stream(**stream_kwargs) as decryptor: for chunk in decryptor: result.extend(chunk) return result, decryptor.header @@ -388,11 +584,13 @@ def manifest_spec(self): return {"manifest": manifest_spec, "client": client_spec, "keys": self.keys_uri, "tests": test_specs} @classmethod - def from_file(cls, input_file): + def from_file(cls, input_file, keyrings): + # pylint: disable=too-many-locals # type: (IO) -> MessageDecryptionManifest """Load from a file containing a full message decrypt manifest. :param file input_file: File object for file containing JSON manifest + :param bool keyrings: True if should decrypt with keyring interfaces; False otherwise :return: Loaded manifest :rtype: MessageDecryptionManifest """ @@ -407,6 +605,11 @@ def from_file(cls, input_file): version = raw_manifest["manifest"]["version"] # type: int keys_uri = raw_manifest["keys"] # type: str + # MPL TestVector keyring needs to know the path to the keys file + keys_uri = raw_manifest["keys"] + keys_filename = keys_uri.replace("file://", "") + keys_abs_path = os.path.join(parent_dir, keys_filename) + raw_keys_manifest = json.loads(root_reader(keys_uri).decode(ENCODING)) keys = KeysManifest.from_manifest_spec(raw_keys_manifest) @@ -415,10 +618,38 @@ def from_file(cls, input_file): raw_scenarios = raw_manifest["tests"] # type: Dict[str, DECRYPT_SCENARIO_SPEC] test_scenarios = { name: MessageDecryptionTestScenario.from_scenario( - scenario=scenario, plaintext_reader=root_reader, ciphertext_reader=root_reader, keys=keys + scenario=scenario, + plaintext_reader=root_reader, + ciphertext_reader=root_reader, + keys=keys, + keyrings=False, + keys_uri=keys_abs_path, ) for name, scenario in raw_scenarios.items() } + # If optional keyrings argument is true, + # also add scenarios to decrypt with keyrings. + if keyrings: + keyrings_test_scenarios = { + name + "-keyring": MessageDecryptionTestScenario.from_scenario( + scenario=scenario, + plaintext_reader=root_reader, + ciphertext_reader=root_reader, + keys=keys, + keyrings=True, + keys_uri=keys_abs_path, + ) + for name, scenario in raw_scenarios.items() + } + # Merge keyring scenarios into test_scenarios + test_scenarios = {**keyrings_test_scenarios, **test_scenarios} + + # Remove any `None` scenarios from test scenarios. + # `None` scenarios indicate the loader determined the scenario is invalid. + # e.g. cmm_type = "RequiredEncryptionContext" with master keys + for name in list(test_scenarios.keys()): + if test_scenarios[name] is None: + del test_scenarios[name] return cls( keys_uri=keys_uri, diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py index e407a1b65..50c14a091 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py @@ -23,10 +23,38 @@ import attr import six from aws_encryption_sdk.caches.local import LocalCryptoMaterialsCache +from aws_encryption_sdk.key_providers.base import MasterKeyProvider from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager from aws_encryption_sdk.materials_managers.caching import CachingCryptoMaterialsManager from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager +try: + from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + from aws_cryptographic_materialproviders.mpl.references import ( + IKeyring, + ) + from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, + ) + from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL + + from awses_test_vectors.manifests.mpl_keyring import KeyringSpec, keyring_from_master_key_specs + + from aws_encryption_sdk.materials_managers.mpl.materials import ( + EncryptionMaterialsFromMPL + ) + from awses_test_vectors.internal.mpl.tampering_mpl_materials import ( + HalfSigningEncryptionMaterialsFromMPL, + ProviderInfoChangingCryptoMaterialsManagerFromMPL, + HalfSigningCryptoMaterialsManagerFromMPL, + ) + + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + + from awses_test_vectors.internal.defaults import ENCODING from awses_test_vectors.internal.util import ( dictionary_validator, @@ -92,9 +120,23 @@ def run_scenario_with_tampering(self, ciphertext_writer, generation_scenario, pl return: a list of (ciphertext, result) pairs """ - materials_manager = DefaultCryptoMaterialsManager( - generation_scenario.encryption_scenario.master_key_provider_fn() - ) + key_provider = generation_scenario.encryption_scenario.master_key_provider_fn() + if isinstance(key_provider, MasterKeyProvider): + materials_manager = DefaultCryptoMaterialsManager( + key_provider + ) + elif _HAS_MPL and isinstance(key_provider, IKeyring): + mpl = AwsCryptographicMaterialProviders(MaterialProvidersConfig()) + mpl_cmm = mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=key_provider + ) + ) + materials_manager = CryptoMaterialsManagerFromMPL( + mpl_cmm=mpl_cmm + ) + else: + raise ValueError(f"Unrecognized master_key_provider_fn return type: {str(key_provider)}") ciphertext_to_decrypt = generation_scenario.encryption_scenario.run(materials_manager) if generation_scenario.result: expected_result = generation_scenario.result @@ -131,16 +173,31 @@ def run_scenario_with_tampering(self, ciphertext_writer, generation_scenario, _p master_key_provider = generation_scenario.encryption_scenario.master_key_provider_fn() # Use a caching CMM to avoid generating a new data key every time. - cache = LocalCryptoMaterialsCache(10) - caching_cmm = CachingCryptoMaterialsManager( - master_key_provider=master_key_provider, - cache=cache, - max_age=60.0, - max_messages_encrypted=100, - ) + if isinstance(master_key_provider, MasterKeyProvider): + cache = LocalCryptoMaterialsCache(10) + caching_cmm = CachingCryptoMaterialsManager( + master_key_provider=master_key_provider, + cache=cache, + max_age=60.0, + max_messages_encrypted=100, + ) + cmm = caching_cmm + # No caching CMM in MPL :( + # Use default CMM + elif _HAS_MPL and isinstance(master_key_provider, IKeyring): + mpl = AwsCryptographicMaterialProviders(MaterialProvidersConfig()) + mpl_cmm = mpl.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=master_key_provider + ) + ) + cmm = CryptoMaterialsManagerFromMPL(mpl_cmm=mpl_cmm) + else: + raise TypeError(f"Unrecognized master_key_provider type: {master_key_provider}") + return [ self.run_scenario_with_new_provider_info( - ciphertext_writer, generation_scenario, caching_cmm, new_provider_info + ciphertext_writer, generation_scenario, cmm, new_provider_info ) for new_provider_info in self.new_provider_infos ] @@ -149,7 +206,18 @@ def run_scenario_with_new_provider_info( self, ciphertext_writer, generation_scenario, materials_manager, new_provider_info ): """Run with tampering for a specific new provider info value""" - tampering_materials_manager = ProviderInfoChangingCryptoMaterialsManager(materials_manager, new_provider_info) + if _HAS_MPL and isinstance(materials_manager, CryptoMaterialsManagerFromMPL): + tampering_materials_manager = ProviderInfoChangingCryptoMaterialsManagerFromMPL( + materials_manager, + new_provider_info + ) + elif isinstance(materials_manager, CryptoMaterialsManager): + tampering_materials_manager = ProviderInfoChangingCryptoMaterialsManager( + materials_manager, + new_provider_info + ) + else: + raise TypeError(f"Unrecognized materials_manager type: {materials_manager}") ciphertext_to_decrypt = generation_scenario.encryption_scenario.run(tampering_materials_manager) expected_result = MessageDecryptionTestResult.expect_error( "Incorrect encrypted data key provider info: " + new_provider_info @@ -253,9 +321,20 @@ def run_scenario_with_tampering(self, ciphertext_writer, generation_scenario, _p return: a list of (ciphertext, result) pairs. """ - tampering_materials_manager = HalfSigningCryptoMaterialsManager( - generation_scenario.encryption_scenario.master_key_provider_fn() - ) + if isinstance( + generation_scenario.encryption_scenario.master_key_provider_fn(), + MasterKeyProvider + ): + tampering_materials_manager = HalfSigningCryptoMaterialsManager( + generation_scenario.encryption_scenario.master_key_provider_fn() + ) + elif _HAS_MPL and isinstance( + generation_scenario.encryption_scenario.master_key_provider_fn(), + IKeyring + ): + tampering_materials_manager = HalfSigningCryptoMaterialsManagerFromMPL( + generation_scenario.encryption_scenario.master_key_provider_fn() + ) ciphertext_to_decrypt = generation_scenario.encryption_scenario.run(tampering_materials_manager) expected_result = MessageDecryptionTestResult.expect_error( "Unsigned message using a data key with a public key" @@ -296,6 +375,11 @@ def get_encryption_materials(self, request): signing_request.algorithm = AlgorithmSuite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 result = self.wrapped_default_cmm.get_encryption_materials(signing_request) + + if _HAS_MPL: + if isinstance(result, EncryptionMaterialsFromMPL): + result = HalfSigningEncryptionMaterialsFromMPL(result) + result.algorithm = request.algorithm result.signing_key = None @@ -326,6 +410,7 @@ class MessageDecryptionTestScenarioGenerator(object): :type decryption_master_key_specs: iterable of :class:`MasterKeySpec` :param Callable decryption_master_key_provider_fn: :param result: + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise """ encryption_scenario = attr.ib(validator=attr.validators.instance_of(MessageEncryptionTestScenario)) @@ -334,29 +419,46 @@ class MessageDecryptionTestScenarioGenerator(object): decryption_master_key_specs = attr.ib(validator=iterable_validator(list, MasterKeySpec)) decryption_master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) result = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(MessageDecryptionTestResult))) + keyrings = attr.ib(validator=attr.validators.instance_of(bool)) @classmethod - def from_scenario(cls, scenario, keys, plaintexts): + def from_scenario(cls, scenario, keys, plaintexts, keyrings, keys_uri): + # pylint: disable=too-many-arguments,too-many-locals """Load from a scenario specification. :param dict scenario: Scenario specification JSON :param KeysManifest keys: Loaded keys :param dict plaintexts: Mapping of plaintext names to plaintext values + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise + :param string keys_uri: Filepath to keys manifest. Used by MPL TestVector keyring constructor. :return: Loaded test scenario :rtype: MessageDecryptionTestScenarioGenerator """ encryption_scenario_spec = scenario["encryption-scenario"] - encryption_scenario = MessageEncryptionTestScenario.from_scenario(encryption_scenario_spec, keys, plaintexts) + encryption_scenario = MessageEncryptionTestScenario.from_scenario( + encryption_scenario_spec, + keys, + plaintexts, + keyrings, + keys_uri, + ) tampering = scenario.get("tampering") tampering_method = TamperingMethod.from_tampering_spec(tampering) decryption_method_spec = scenario.get("decryption-method") decryption_method = DecryptionMethod(decryption_method_spec) if decryption_method_spec else None if "decryption-master-keys" in scenario: - decryption_master_key_specs = [ - MasterKeySpec.from_scenario(spec) for spec in scenario["decryption-master-keys"] - ] + if keyrings: + decryption_master_key_specs = [ + KeyringSpec.from_scenario(spec) for spec in scenario["decryption-master-keys"] + ] + else: + decryption_master_key_specs = [ + MasterKeySpec.from_scenario(spec) for spec in scenario["decryption-master-keys"] + ] def decryption_master_key_provider_fn(): + if keyrings: + return keyring_from_master_key_specs(keys_uri, decryption_master_key_specs, "decrypt-generation") return master_key_provider_from_master_key_specs(keys, decryption_master_key_specs) else: @@ -372,6 +474,7 @@ def decryption_master_key_provider_fn(): decryption_master_key_specs=decryption_master_key_specs, decryption_master_key_provider_fn=decryption_master_key_provider_fn, result=result, + keyrings=keyrings, ) def run(self, ciphertext_writer, plaintext_uri): @@ -400,6 +503,9 @@ def decryption_test_scenario_pair(self, ciphertext_writer, ciphertext_to_decrypt master_key_provider_fn=self.decryption_master_key_provider_fn, decryption_method=self.decryption_method, result=expected_result, + keyrings=self.keyrings, + cmm_type="Default", + encryption_context={} ), ) @@ -414,12 +520,14 @@ class MessageDecryptionGenerationManifest(object): :param KeysManifest keys: Loaded keys :param dict plaintexts: Mapping of plaintext names to plaintext values :param dict tests: Mapping of test scenario names to :class:`MessageDecryptionGenerationManifest`s + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise """ version = attr.ib(validator=membership_validator(SUPPORTED_VERSIONS)) keys = attr.ib(validator=attr.validators.instance_of(KeysManifest)) plaintexts = attr.ib(validator=dictionary_validator(six.string_types, six.binary_type)) tests = attr.ib(validator=dictionary_validator(six.string_types, MessageDecryptionTestScenarioGenerator)) + keyrings = attr.ib(validator=attr.validators.instance_of(bool)) type_name = "awses-decrypt-generate" @staticmethod @@ -434,11 +542,12 @@ def _generate_plaintexts(plaintexts_specs): return {name: os.urandom(size) for name, size in plaintexts_specs.items()} @classmethod - def from_file(cls, input_file): + def from_file(cls, input_file, keyrings): # type: (IO) -> MessageDecryptionGenerationManifest """Load from a file containing a full message encrypt manifest. :param file input_file: File object for file containing JSON manifest + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise :return: Loaded manifest :rtype: MessageEncryptionManifest """ @@ -449,18 +558,30 @@ def from_file(cls, input_file): parent_dir = os.path.abspath(os.path.dirname(input_file.name)) reader = file_reader(parent_dir) - raw_keys_manifest = json.loads(reader(raw_manifest["keys"]).decode(ENCODING)) + + # MPL TestVector keyring needs to know the path to the keys file + keys_uri = raw_manifest["keys"] + keys_filename = keys_uri.replace("file://", "") + keys_abs_path = os.path.join(parent_dir, keys_filename) + + raw_keys_manifest = json.loads(reader(keys_uri).decode(ENCODING)) keys = KeysManifest.from_manifest_spec(raw_keys_manifest) plaintexts = cls._generate_plaintexts(raw_manifest["plaintexts"]) tests = {} for name, scenario in raw_manifest["tests"].items(): try: tests[name] = MessageDecryptionTestScenarioGenerator.from_scenario( - scenario=scenario, keys=keys, plaintexts=plaintexts + scenario=scenario, keys=keys, plaintexts=plaintexts, keyrings=keyrings, keys_uri=keys_abs_path, ) except NotImplementedError: continue - return cls(version=raw_manifest["manifest"]["version"], keys=keys, plaintexts=plaintexts, tests=tests) + return cls( + version=raw_manifest["manifest"]["version"], + keys=keys, + plaintexts=plaintexts, + tests=tests, + keyrings=keyrings, + ) def run_and_write_to_dir(self, target_directory, json_indent=None): # type: (str, Optional[int]) -> None diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py index c77fed1ce..57de8504c 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py @@ -22,6 +22,8 @@ import aws_encryption_sdk import six +from aws_encryption_sdk.key_providers.base import MasterKeyProvider + from awses_test_vectors.internal.defaults import ENCODING from awses_test_vectors.internal.util import ( algorithm_suite_from_string_id, @@ -34,11 +36,23 @@ from awses_test_vectors.manifests.keys import KeysManifest from awses_test_vectors.manifests.master_key import MasterKeySpec, master_key_provider_from_master_key_specs + try: from aws_encryption_sdk.identifiers import AlgorithmSuite, CommitmentPolicy except ImportError: from aws_encryption_sdk.identifiers import Algorithm as AlgorithmSuite +try: + from aws_cryptographic_materialproviders.mpl.references import ( + IKeyring, + ) + + from awses_test_vectors.manifests.mpl_keyring import KeyringSpec, keyring_from_master_key_specs + + _HAS_MPL = True +except ImportError: + _HAS_MPL = False + try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import IO, Callable, Dict, Iterable, Optional # noqa pylint: disable=unused-import @@ -78,22 +92,36 @@ class MessageEncryptionTestScenario(object): encryption_context = attr.ib(validator=dictionary_validator(six.string_types, six.string_types)) master_key_specs = attr.ib(validator=iterable_validator(list, MasterKeySpec)) master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) + keyrings = attr.ib(validator=attr.validators.instance_of(bool)) @classmethod - def from_scenario(cls, scenario, keys, plaintexts): - # type: (ENCRYPT_SCENARIO_SPEC, KeysManifest, Dict[str, bytes]) -> MessageEncryptionTestScenario + def from_scenario(cls, scenario, keys, plaintexts, keyrings, keys_uri): + # pylint: disable=too-many-arguments + # type: (ENCRYPT_SCENARIO_SPEC, KeysManifest, Dict[str, bytes], bool, str) -> MessageEncryptionTestScenario """Load from a scenario specification. :param dict scenario: Scenario specification JSON :param KeysManifest keys: Loaded keys :param dict plaintexts: Mapping of plaintext names to plaintext values + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise + :param str keys_uri: Path to the keys manifest :return: Loaded test scenario :rtype: MessageEncryptionTestScenario """ algorithm = algorithm_suite_from_string_id(scenario["algorithm"]) - master_key_specs = [MasterKeySpec.from_scenario(spec) for spec in scenario["master-keys"]] + + if keyrings: + master_key_specs = [ + KeyringSpec.from_scenario(spec) for spec in scenario["master-keys"] + ] + else: + master_key_specs = [ + MasterKeySpec.from_scenario(spec) for spec in scenario["master-keys"] + ] def master_key_provider_fn(): + if keyrings: + return keyring_from_master_key_specs(keys_uri, master_key_specs, "encrypt") return master_key_provider_from_master_key_specs(keys, master_key_specs) return cls( @@ -104,6 +132,7 @@ def master_key_provider_fn(): encryption_context=scenario["encryption-context"], master_key_specs=master_key_specs, master_key_provider_fn=master_key_provider_fn, + keyrings=keyrings, ) def run(self, materials_manager=None): @@ -129,8 +158,12 @@ def run(self, materials_manager=None): ) if materials_manager: encrypt_kwargs["materials_manager"] = materials_manager - else: + elif isinstance(self.master_key_provider_fn(), MasterKeyProvider): encrypt_kwargs["key_provider"] = self.master_key_provider_fn() + elif _HAS_MPL and isinstance(self.master_key_provider_fn(), IKeyring): + encrypt_kwargs["keyring"] = self.master_key_provider_fn() + else: + raise TypeError(f"Unrecognized master_key_provider_fn return type: {self.master_key_provider_fn()}") ciphertext, _header = client.encrypt(**encrypt_kwargs) return ciphertext @@ -165,11 +198,12 @@ def _generate_plaintexts(plaintexts_specs): return {name: os.urandom(size) for name, size in plaintexts_specs.items()} @classmethod - def from_file(cls, input_file): + def from_file(cls, input_file, keyrings): # type: (IO) -> MessageEncryptionManifest """Load frome a file containing a full message encrypt manifest. :param file input_file: File object for file containing JSON manifest + :param bool keyrings: True if should encrypt with keyring interfaces; False otherwise :return: Loaded manifest :rtype: MessageEncryptionManifest """ @@ -180,14 +214,20 @@ def from_file(cls, input_file): parent_dir = os.path.abspath(os.path.dirname(input_file.name)) reader = file_reader(parent_dir) - raw_keys_manifest = json.loads(reader(raw_manifest["keys"]).decode(ENCODING)) + + # MPL TestVector keyring needs to know the path to the keys file + keys_uri = raw_manifest["keys"] + keys_filename = keys_uri.replace("file://", "") + keys_abs_path = os.path.join(parent_dir, keys_filename) + + raw_keys_manifest = json.loads(reader(keys_uri).decode(ENCODING)) keys = KeysManifest.from_manifest_spec(raw_keys_manifest) plaintexts = cls._generate_plaintexts(raw_manifest["plaintexts"]) tests = {} for name, scenario in raw_manifest["tests"].items(): try: tests[name] = MessageEncryptionTestScenario.from_scenario( - scenario=scenario, keys=keys, plaintexts=plaintexts + scenario=scenario, keys=keys, plaintexts=plaintexts, keyrings=keyrings, keys_uri=keys_abs_path ) except NotImplementedError: continue diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py new file mode 100644 index 000000000..ec35147c0 --- /dev/null +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -0,0 +1,182 @@ +# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Keyring Manifest handler. + +This REQUIRES the aws-cryptographic-material-providers library. +""" +import json +import attr + +# Ignore missing MPL for pylint, but the MPL is required for this example +# noqa pylint: disable=import-error +from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ + aws_cryptography_materialproviderstestvectorkeys.models import ( + GetKeyDescriptionInput, + GetKeyDescriptionOutput, + TestVectorKeyringInput, + ) +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_materialproviders.mpl.models import CreateMultiKeyringInput + +import _dafny +import UTF8 + +# Ignore pylint not being able to read a module that requires the MPL +# pylint: disable=no-name-in-module +from awses_test_vectors.internal.mpl.keyvectors_provider import KeyVectorsProvider +from awses_test_vectors.manifests.keys import KeysManifest # noqa: disable=F401 + + +from .master_key import MasterKeySpec + + +@attr.s +class KeyringSpec(MasterKeySpec): # pylint: disable=too-many-instance-attributes + """AWS Encryption SDK master key specification utilities. + + Described in AWS Crypto Tools Test Vector Framework features #0003 and #0004. + + :param str type_name: Master key type name + :param str key_name: Name of key in keys spec + :param str provider_id: Master key provider ID + :param str encryption_algorithm: Wrapping key encryption algorithm (required for raw master keys) + :param str padding_algorithm: Wrapping key padding algorithm (required for raw master keys) + :param str padding_hash: Wrapping key padding hash (required for raw master keys) + """ + + def keyring(self, keys_uri, mode): + # type: (KeysManifest) -> IKeyring + """Build a keyring using this specification. + :param str keys_uri: Path to the keys manifest + """ + keyvectors = KeyVectorsProvider.get_keyvectors(keys_path=keys_uri) + + # Variable to flag whether we changed anything in weird hack #1. + # Signals to weird hack #2 whether it should execute. + changed_key_name_from_private_to_public = False + + # Construct the input to KeyVectorsConfig + input_kwargs = { + "type": self.type_name, + "key": self.key_name, + "provider-id": self.provider_id, + "encryption-algorithm": self.encryption_algorithm, + + } + if self.padding_algorithm is not None and self.padding_algorithm != "": + input_kwargs["padding-algorithm"] = self.padding_algorithm + if self.padding_hash is not None: + input_kwargs["padding-hash"] = self.padding_hash + + if input_kwargs["type"] == "raw" \ + and input_kwargs["encryption-algorithm"] == "rsa": + # Weird hack #1: + # Gets public key for encryption instead of private key. + # + # If generating decrypt vectors (i.e. encrypting) + # and the manifest specified an RSA private key, + # change the input to KeyVectors to a public key. + # KeyVectors requires a public key to encrypt. + # If this is not done, then keyring.OnEncrypt fails with + # "A RawRSAKeyring without a public key cannot provide OnEncrypt" + if input_kwargs["key"] == "rsa-4096-private" \ + and mode in ("decrypt-generate", "encrypt"): + changed_key_name_from_private_to_public = True + input_kwargs["key"] = "rsa-4096-public" + # Specify default padding-hash + if "padding-hash" not in input_kwargs: + input_kwargs["padding-hash"] = "sha1" + + # stringify the dict + input_as_string = json.dumps(input_kwargs) + # convert to unicode code point (expected representation) + encoded_json = [ord(c) for c in input_as_string] + + output: GetKeyDescriptionOutput = keyvectors.get_key_description( + GetKeyDescriptionInput(json=encoded_json) + ) + + keyring: IKeyring = keyvectors.create_test_vector_keyring( + TestVectorKeyringInput( + key_description=output.key_description + ) + ) + + # Weird hack #2: + # Sets keyProviderInfo to "private" even though the material is "public". + # + # Weird hack #1 allows the encrypting keyring to be created with a public key. + # However, it also changes the keyName of the encrypting keyring. + # This hack changes it back. + # + # If this is not done, then decryption fails + # (for BOTH native master keys and MPL keyrings) + # with error + # native master keys: "Unable to decrypt any data key" + # MPL: "Raw RSA Key was unable to decrypt any encrypted data key" + # + # Digging, the keyring is unable to decrypt in the MPL + # because the EDK keyProviderInfo differs from the keyring keyName, + # and this check fails: + # https://github.com/aws/aws-cryptographic-material-providers-library/blob/bd549c88cefc93ba8a2d204bd23134b3b12c69fb/AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/src/Keyrings/RawRSAKeyring.dfy#L382 + # due to the two variables not being equal: + # edk.keyProviderInfo='rsa-4096-public' + # keyring.keyName='rsa-4096-private' + # + # Changing the encrypting keyring's keyName back to 'rsa-4096-private' + # sets any EDKs this keyring encrypts to now have + # keyName="rsa-4096-private". + # However, keyvectors has still retrieved the public key material to encrypt with. + # So it any EDKs it encrypts will use the public material, but have keyName="rsa-4096-private". + # + # This configuration seems to be correct, because + # all of the test vectors (master keys and MPL) pass with these two hacks. + # But this seems weird, and we didn't have to do this in Java. + if hasattr(keyring, "_impl"): # pylint: disable=protected-access + if hasattr(keyring._impl, "_keyName"): # pylint: disable=protected-access + if keyring._impl._keyName == UTF8.default__.Encode(_dafny.Seq("rsa-4096-public")).value \ + and mode in ("decrypt-generate", "encrypt"): # pylint: disable=protected-access + if changed_key_name_from_private_to_public: + # pylint: disable=protected-access + keyring._impl._keyName = UTF8.default__.Encode(_dafny.Seq("rsa-4096-private")).value + + return keyring + + +def keyring_from_master_key_specs(keys_uri, master_key_specs, mode): + # type: (str, list[KeyringSpec]) -> IKeyring + """Build and combine all keyrings identified by the provided specs and + using the provided keys. + + :param str keys_uri: Path to the keys manifest + :param master_key_specs: Master key specs from which to load master keys + :type master_key_specs: iterable of MasterKeySpec + :return: Master key provider combining all loaded master keys + :rtype: IKeyring + """ + keyrings = [spec.keyring(keys_uri, mode) for spec in master_key_specs] + primary = keyrings[0] + others = keyrings[1:] + + mpl: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + MaterialProvidersConfig() + ) + multi_keyring: IKeyring = mpl.create_multi_keyring( + CreateMultiKeyringInput( + generator=primary, + child_keyrings=others + ) + ) + return multi_keyring diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index 580b641e0..cdb1137fb 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -36,7 +36,7 @@ envlist = # release :: Builds dist files and uploads to pypi pypirc profile. [testenv:base-command] -commands = pytest --basetemp={envtmpdir} -l --cov awses_test_vectors test/ {posargs} +commands = pytest --basetemp={envtmpdir} -l --cov awses_test_vectors test/ --ignore test/mpl {posargs} [testenv] passenv = @@ -50,10 +50,13 @@ sitepackages = False deps = -rtest/requirements.txt # Install the MPL requirements if the `-mpl` suffix is present - mpl: -r../requirements_mpl.txt + mpl: -rrequirements_mpl.txt .. commands = - {[testenv:base-command]commands} + awses_local: {[testenv:base-command]commands} + full_decrypt_generate: awses-full-message-decrypt-generate {posargs} + full_decrypt: awses-full-message-decrypt {posargs} + full_encrypt: awses-full-message-encrypt {posargs} [testenv:full-encrypt] basepython = python3 From 70d1364663aa1c7241ba96506b3d6eea865ea82b Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Fri, 10 May 2024 10:52:40 -0700 Subject: [PATCH 11/51] chore(keyring examples): refactor keyring examples and move master key provider examples to legacy (#678) --- examples/src/__init__.py | 14 +----- .../aws_kms_discovery_keyring_example.py | 2 +- ...aws_kms_discovery_multi_keyring_example.py | 4 +- .../{keyrings => }/aws_kms_keyring_example.py | 2 +- .../aws_kms_mrk_discovery_keyring_example.py | 2 +- ...kms_mrk_discovery_multi_keyring_example.py | 4 +- .../aws_kms_mrk_keyring_example.py | 2 +- .../aws_kms_mrk_multi_keyring_example.py | 2 +- .../aws_kms_multi_keyring_example.py | 2 +- .../aws_kms_rsa_keyring_example.py | 2 +- .../branch_key_id_supplier_example.py | 2 +- .../{keyrings => }/file_streaming_example.py | 2 +- .../hierarchical_keyring_example.py | 2 +- examples/src/{keyrings => legacy}/__init__.py | 0 examples/src/{ => legacy}/basic_encryption.py | 0 ...file_encryption_with_multiple_providers.py | 0 ...c_file_encryption_with_raw_key_provider.py | 0 .../custom_kms_client_for_kms_provider.py | 0 .../{ => legacy}/data_key_caching_basic.py | 0 .../{ => legacy}/discovery_kms_provider.py | 0 examples/src/{keyrings => legacy}/module_.py | 0 .../{ => legacy}/mrk_aware_kms_provider.py | 0 examples/src/{ => legacy}/multiple_kms_cmk.py | 0 examples/src/{ => legacy}/one_kms_cmk.py | 0 .../one_kms_cmk_streaming_data.py | 0 .../src/{ => legacy}/one_kms_cmk_unsigned.py | 0 examples/src/legacy/pylintrc | 44 +++++++++++++++++++ examples/src/{ => legacy}/set_commitment.py | 0 ...migration_set_commitment_policy_example.py | 2 +- .../{keyrings => }/multi_keyring_example.py | 2 +- examples/src/pylintrc | 1 + .../{keyrings => }/raw_aes_keyring_example.py | 2 +- .../{keyrings => }/raw_rsa_keyring_example.py | 4 +- .../required_encryption_context_cmm.py | 5 ++- .../set_encryption_algorithm_suite_example.py | 2 +- examples/test/__init__.py | 14 +----- .../test/{keyrings => legacy}/__init__.py | 0 .../test/{ => legacy}/examples_test_utils.py | 2 +- examples/test/legacy/pylintrc | 22 ++++++++++ .../{ => legacy}/test_i_basic_encryption.py | 3 +- ...file_encryption_with_multiple_providers.py | 6 +-- ...c_file_encryption_with_raw_key_provider.py | 3 +- .../test_i_data_key_caching_basic.py | 3 +- .../test_i_discovery_kms_provider.py | 6 +-- .../test_i_mrk_aware_kms_provider.py | 6 +-- .../{ => legacy}/test_i_multiple_kms_cmk.py | 6 +-- .../test/{ => legacy}/test_i_one_kms_cmk.py | 6 +-- .../test_i_one_kms_cmk_streaming_data.py | 3 +- .../test_i_one_kms_cmk_unsigned.py | 6 +-- .../{ => legacy}/test_i_set_commitment.py | 6 +-- examples/test/pylintrc | 1 + ...est_i_aws_kms_discovery_keyring_example.py | 2 +- ...aws_kms_discovery_multi_keyring_example.py | 2 +- .../test_i_aws_kms_keyring_example.py | 2 +- ...i_aws_kms_mrk_discovery_keyring_example.py | 2 +- ...kms_mrk_discovery_multi_keyring_example.py | 2 +- .../test_i_aws_kms_mrk_keyring_example.py | 2 +- ...est_i_aws_kms_mrk_multi_keyring_example.py | 2 +- .../test_i_aws_kms_multi_keyring_example.py | 2 +- .../test_i_aws_kms_rsa_keyring_example.py | 2 +- .../test_i_file_streaming_example.py | 2 +- .../test_i_hierarchical_keyring_example.py | 2 +- ...migration_set_commitment_policy_example.py | 2 +- .../test_i_multi_keyring_example.py | 2 +- .../test_i_raw_aes_keyring_example.py | 2 +- .../test_i_raw_rsa_keyring_example.py | 6 +-- .../test_i_required_encryption_context_cmm.py | 2 +- ..._set_encryption_algorithm_suite_example.py | 2 +- tox.ini | 10 ++--- 69 files changed, 138 insertions(+), 107 deletions(-) rename examples/src/{keyrings => }/aws_kms_discovery_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_discovery_multi_keyring_example.py (98%) rename examples/src/{keyrings => }/aws_kms_keyring_example.py (98%) rename examples/src/{keyrings => }/aws_kms_mrk_discovery_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_mrk_discovery_multi_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_mrk_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_mrk_multi_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_multi_keyring_example.py (99%) rename examples/src/{keyrings => }/aws_kms_rsa_keyring_example.py (98%) rename examples/src/{keyrings => }/branch_key_id_supplier_example.py (96%) rename examples/src/{keyrings => }/file_streaming_example.py (99%) rename examples/src/{keyrings => }/hierarchical_keyring_example.py (99%) rename examples/src/{keyrings => legacy}/__init__.py (100%) rename examples/src/{ => legacy}/basic_encryption.py (100%) rename examples/src/{ => legacy}/basic_file_encryption_with_multiple_providers.py (100%) rename examples/src/{ => legacy}/basic_file_encryption_with_raw_key_provider.py (100%) rename examples/src/{ => legacy}/custom_kms_client_for_kms_provider.py (100%) rename examples/src/{ => legacy}/data_key_caching_basic.py (100%) rename examples/src/{ => legacy}/discovery_kms_provider.py (100%) rename examples/src/{keyrings => legacy}/module_.py (100%) rename examples/src/{ => legacy}/mrk_aware_kms_provider.py (100%) rename examples/src/{ => legacy}/multiple_kms_cmk.py (100%) rename examples/src/{ => legacy}/one_kms_cmk.py (100%) rename examples/src/{ => legacy}/one_kms_cmk_streaming_data.py (100%) rename examples/src/{ => legacy}/one_kms_cmk_unsigned.py (100%) create mode 100644 examples/src/legacy/pylintrc rename examples/src/{ => legacy}/set_commitment.py (100%) rename examples/src/{keyrings => }/migration_set_commitment_policy_example.py (98%) rename examples/src/{keyrings => }/multi_keyring_example.py (99%) rename examples/src/{keyrings => }/raw_aes_keyring_example.py (98%) rename examples/src/{keyrings => }/raw_rsa_keyring_example.py (98%) rename examples/src/{keyrings => }/required_encryption_context_cmm.py (98%) rename examples/src/{keyrings => }/set_encryption_algorithm_suite_example.py (99%) rename examples/test/{keyrings => legacy}/__init__.py (100%) rename examples/test/{ => legacy}/examples_test_utils.py (98%) create mode 100644 examples/test/legacy/pylintrc rename examples/test/{ => legacy}/test_i_basic_encryption.py (94%) rename examples/test/{ => legacy}/test_i_basic_file_encryption_with_multiple_providers.py (87%) rename examples/test/{ => legacy}/test_i_basic_file_encryption_with_raw_key_provider.py (93%) rename examples/test/{ => legacy}/test_i_data_key_caching_basic.py (92%) rename examples/test/{ => legacy}/test_i_discovery_kms_provider.py (85%) rename examples/test/{ => legacy}/test_i_mrk_aware_kms_provider.py (90%) rename examples/test/{ => legacy}/test_i_multiple_kms_cmk.py (90%) rename examples/test/{ => legacy}/test_i_one_kms_cmk.py (86%) rename examples/test/{ => legacy}/test_i_one_kms_cmk_streaming_data.py (94%) rename examples/test/{ => legacy}/test_i_one_kms_cmk_unsigned.py (86%) rename examples/test/{ => legacy}/test_i_set_commitment.py (86%) rename examples/test/{keyrings => }/test_i_aws_kms_discovery_keyring_example.py (86%) rename examples/test/{keyrings => }/test_i_aws_kms_discovery_multi_keyring_example.py (86%) rename examples/test/{keyrings => }/test_i_aws_kms_keyring_example.py (85%) rename examples/test/{keyrings => }/test_i_aws_kms_mrk_discovery_keyring_example.py (89%) rename examples/test/{keyrings => }/test_i_aws_kms_mrk_discovery_multi_keyring_example.py (88%) rename examples/test/{keyrings => }/test_i_aws_kms_mrk_keyring_example.py (91%) rename examples/test/{keyrings => }/test_i_aws_kms_mrk_multi_keyring_example.py (90%) rename examples/test/{keyrings => }/test_i_aws_kms_multi_keyring_example.py (90%) rename examples/test/{keyrings => }/test_i_aws_kms_rsa_keyring_example.py (93%) rename examples/test/{keyrings => }/test_i_file_streaming_example.py (97%) rename examples/test/{keyrings => }/test_i_hierarchical_keyring_example.py (86%) rename examples/test/{keyrings => }/test_i_migration_set_commitment_policy_example.py (83%) rename examples/test/{keyrings => }/test_i_multi_keyring_example.py (85%) rename examples/test/{keyrings => }/test_i_raw_aes_keyring_example.py (81%) rename examples/test/{keyrings => }/test_i_raw_rsa_keyring_example.py (93%) rename examples/test/{keyrings => }/test_i_required_encryption_context_cmm.py (81%) rename examples/test/{keyrings => }/test_i_set_encryption_algorithm_suite_example.py (79%) diff --git a/examples/src/__init__.py b/examples/src/__init__.py index e8fd618b1..120179eda 100644 --- a/examples/src/__init__.py +++ b/examples/src/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Stub module indicator to make linter configuration simpler.""" diff --git a/examples/src/keyrings/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_discovery_keyring_example.py rename to examples/src/aws_kms_discovery_keyring_example.py index 53d9cf1e4..4695e8783 100644 --- a/examples/src/keyrings/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -43,7 +43,7 @@ DiscoveryFilter, ) from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py similarity index 98% rename from examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py rename to examples/src/aws_kms_discovery_multi_keyring_example.py index adfadec37..60d74ff31 100644 --- a/examples/src/keyrings/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -40,7 +40,7 @@ DiscoveryFilter, ) from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy @@ -56,7 +56,7 @@ def encrypt_and_decrypt_with_keyring( kms_key_id: str, aws_account_id: str, - aws_regions: list[str] + aws_regions: list ): """Demonstrate an encrypt/decrypt cycle using an AWS KMS Discovery Multi Keyring. diff --git a/examples/src/keyrings/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py similarity index 98% rename from examples/src/keyrings/aws_kms_keyring_example.py rename to examples/src/aws_kms_keyring_example.py index 4d04ba538..b166aab99 100644 --- a/examples/src/keyrings/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -24,7 +24,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py rename to examples/src/aws_kms_mrk_discovery_keyring_example.py index 63233a068..8ba80b621 100644 --- a/examples/src/keyrings/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -45,7 +45,7 @@ DiscoveryFilter, ) from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py rename to examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index d8ea9bc4c..47cb80f1d 100644 --- a/examples/src/keyrings/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -47,7 +47,7 @@ DiscoveryFilter, ) from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy @@ -64,7 +64,7 @@ def encrypt_and_decrypt_with_keyring( mrk_key_id_encrypt: str, mrk_encrypt_region: str, aws_account_id: str, - aws_regions: list[str] + aws_regions: list ): """Demonstrate decryption using an AWS KMS MRK Discovery Multi keyring. diff --git a/examples/src/keyrings/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_mrk_keyring_example.py rename to examples/src/aws_kms_mrk_keyring_example.py index d5342ba64..65d8be71b 100644 --- a/examples/src/keyrings/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -28,7 +28,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py rename to examples/src/aws_kms_mrk_multi_keyring_example.py index e5445a87c..9c87008fe 100644 --- a/examples/src/keyrings/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -34,7 +34,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput, CreateAwsKmsMrkMultiKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py similarity index 99% rename from examples/src/keyrings/aws_kms_multi_keyring_example.py rename to examples/src/aws_kms_multi_keyring_example.py index 9662405d6..715181646 100644 --- a/examples/src/keyrings/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -43,7 +43,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput, CreateAwsKmsMultiKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py similarity index 98% rename from examples/src/keyrings/aws_kms_rsa_keyring_example.py rename to examples/src/aws_kms_rsa_keyring_example.py index 536581eb8..337dd14b6 100644 --- a/examples/src/keyrings/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -21,7 +21,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsRsaKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/branch_key_id_supplier_example.py b/examples/src/branch_key_id_supplier_example.py similarity index 96% rename from examples/src/keyrings/branch_key_id_supplier_example.py rename to examples/src/branch_key_id_supplier_example.py index 7b390cdda..b3d26497b 100644 --- a/examples/src/keyrings/branch_key_id_supplier_example.py +++ b/examples/src/branch_key_id_supplier_example.py @@ -4,7 +4,7 @@ from aws_cryptographic_materialproviders.mpl.models import GetBranchKeyIdInput, GetBranchKeyIdOutput from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order class ExampleBranchKeyIdSupplier(IBranchKeyIdSupplier): diff --git a/examples/src/keyrings/file_streaming_example.py b/examples/src/file_streaming_example.py similarity index 99% rename from examples/src/keyrings/file_streaming_example.py rename to examples/src/file_streaming_example.py index b7352ba0e..72decde60 100644 --- a/examples/src/keyrings/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -31,7 +31,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py similarity index 99% rename from examples/src/keyrings/hierarchical_keyring_example.py rename to examples/src/hierarchical_keyring_example.py index 7020b68b4..c781f4f40 100644 --- a/examples/src/keyrings/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -47,7 +47,7 @@ DefaultCache, ) from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier, IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/__init__.py b/examples/src/legacy/__init__.py similarity index 100% rename from examples/src/keyrings/__init__.py rename to examples/src/legacy/__init__.py diff --git a/examples/src/basic_encryption.py b/examples/src/legacy/basic_encryption.py similarity index 100% rename from examples/src/basic_encryption.py rename to examples/src/legacy/basic_encryption.py diff --git a/examples/src/basic_file_encryption_with_multiple_providers.py b/examples/src/legacy/basic_file_encryption_with_multiple_providers.py similarity index 100% rename from examples/src/basic_file_encryption_with_multiple_providers.py rename to examples/src/legacy/basic_file_encryption_with_multiple_providers.py diff --git a/examples/src/basic_file_encryption_with_raw_key_provider.py b/examples/src/legacy/basic_file_encryption_with_raw_key_provider.py similarity index 100% rename from examples/src/basic_file_encryption_with_raw_key_provider.py rename to examples/src/legacy/basic_file_encryption_with_raw_key_provider.py diff --git a/examples/src/custom_kms_client_for_kms_provider.py b/examples/src/legacy/custom_kms_client_for_kms_provider.py similarity index 100% rename from examples/src/custom_kms_client_for_kms_provider.py rename to examples/src/legacy/custom_kms_client_for_kms_provider.py diff --git a/examples/src/data_key_caching_basic.py b/examples/src/legacy/data_key_caching_basic.py similarity index 100% rename from examples/src/data_key_caching_basic.py rename to examples/src/legacy/data_key_caching_basic.py diff --git a/examples/src/discovery_kms_provider.py b/examples/src/legacy/discovery_kms_provider.py similarity index 100% rename from examples/src/discovery_kms_provider.py rename to examples/src/legacy/discovery_kms_provider.py diff --git a/examples/src/keyrings/module_.py b/examples/src/legacy/module_.py similarity index 100% rename from examples/src/keyrings/module_.py rename to examples/src/legacy/module_.py diff --git a/examples/src/mrk_aware_kms_provider.py b/examples/src/legacy/mrk_aware_kms_provider.py similarity index 100% rename from examples/src/mrk_aware_kms_provider.py rename to examples/src/legacy/mrk_aware_kms_provider.py diff --git a/examples/src/multiple_kms_cmk.py b/examples/src/legacy/multiple_kms_cmk.py similarity index 100% rename from examples/src/multiple_kms_cmk.py rename to examples/src/legacy/multiple_kms_cmk.py diff --git a/examples/src/one_kms_cmk.py b/examples/src/legacy/one_kms_cmk.py similarity index 100% rename from examples/src/one_kms_cmk.py rename to examples/src/legacy/one_kms_cmk.py diff --git a/examples/src/one_kms_cmk_streaming_data.py b/examples/src/legacy/one_kms_cmk_streaming_data.py similarity index 100% rename from examples/src/one_kms_cmk_streaming_data.py rename to examples/src/legacy/one_kms_cmk_streaming_data.py diff --git a/examples/src/one_kms_cmk_unsigned.py b/examples/src/legacy/one_kms_cmk_unsigned.py similarity index 100% rename from examples/src/one_kms_cmk_unsigned.py rename to examples/src/legacy/one_kms_cmk_unsigned.py diff --git a/examples/src/legacy/pylintrc b/examples/src/legacy/pylintrc new file mode 100644 index 000000000..858fa4d96 --- /dev/null +++ b/examples/src/legacy/pylintrc @@ -0,0 +1,44 @@ +[MESSAGE CONTROL] +# Disabling messages that either we don't care about we intentionally break. +disable = + invalid-name, # we prefer long, descriptive, names for examples + bad-continuation, # we let black handle this + ungrouped-imports, # we let isort handle this + no-member, # breaks with attrs + no-self-use, # interesting to keep in mind for later refactoring, but not blocking + useless-object-inheritance, # we need to support Python 2, so no, not useless + duplicate-code, # some examples may be similar + too-few-public-methods, # does not allow value stores + too-many-locals, # examples may sometimes have more locals defined for clarity than would be appropriate in code + no-else-return, # we omit this on purpose for brevity where it would add no value + attribute-defined-outside-init, # breaks with attrs_post_init + abstract-method, # throws false positives on io.BaseIO grandchildren + redefined-outer-name, # we do this on purpose in multiple places + consider-using-f-string # disable until 2022-05-05; 6 months after 3.5 deprecation + +[BASIC] +# Allow function names up to 50 characters +function-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow method names up to 50 characters +method-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow class attribute names up to 50 characters +# Whitelist class attribute names: iv +class-attribute-rgx = (([A-Za-z_][A-Za-z0-9_]{2,50}|(__.*__))$)|(^iv$) +# Whitelist attribute names: iv +attr-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$) +# Whitelist argument names: iv, b +argument-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$) +# Whitelist variable names: iv, b, _b, x, y, r, s +variable-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$)|(^_b$)|(^x$)|(^y$)|(^r$)|(^s$) + +[VARIABLES] +additional-builtins = raw_input + +[DESIGN] +max-args = 10 + +[FORMAT] +max-line-length = 120 + +[REPORTS] +msg-template = {path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/examples/src/set_commitment.py b/examples/src/legacy/set_commitment.py similarity index 100% rename from examples/src/set_commitment.py rename to examples/src/legacy/set_commitment.py diff --git a/examples/src/keyrings/migration_set_commitment_policy_example.py b/examples/src/migration_set_commitment_policy_example.py similarity index 98% rename from examples/src/keyrings/migration_set_commitment_policy_example.py rename to examples/src/migration_set_commitment_policy_example.py index 0a9e6a3a6..4bd0bc372 100644 --- a/examples/src/keyrings/migration_set_commitment_policy_example.py +++ b/examples/src/migration_set_commitment_policy_example.py @@ -27,7 +27,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/multi_keyring_example.py b/examples/src/multi_keyring_example.py similarity index 99% rename from examples/src/keyrings/multi_keyring_example.py rename to examples/src/multi_keyring_example.py index fd9968f59..b12ab61a3 100644 --- a/examples/src/keyrings/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -49,7 +49,7 @@ CreateRawAesKeyringInput, ) from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/pylintrc b/examples/src/pylintrc index 858fa4d96..8ed5cb105 100644 --- a/examples/src/pylintrc +++ b/examples/src/pylintrc @@ -1,6 +1,7 @@ [MESSAGE CONTROL] # Disabling messages that either we don't care about we intentionally break. disable = + import-error, # ignore mpl import errors invalid-name, # we prefer long, descriptive, names for examples bad-continuation, # we let black handle this ungrouped-imports, # we let isort handle this diff --git a/examples/src/keyrings/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py similarity index 98% rename from examples/src/keyrings/raw_aes_keyring_example.py rename to examples/src/raw_aes_keyring_example.py index be37886da..d8634f774 100644 --- a/examples/src/keyrings/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -29,7 +29,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/keyrings/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py similarity index 98% rename from examples/src/keyrings/raw_rsa_keyring_example.py rename to examples/src/raw_rsa_keyring_example.py index faf617209..4a38fd166 100644 --- a/examples/src/keyrings/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -42,7 +42,7 @@ from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy @@ -240,7 +240,7 @@ def encrypt_and_decrypt_with_keyring(public_key_file_name=None, private_key_file # 10. Test decrypt for the original ciphertext using raw_rsa_keyring_bob try: - plaintext_bytes_bob, _ = client.decrypt( + plaintext_bytes_bob, _ = client.decrypt( # pylint: disable=unused-variable source=ciphertext, keyring=raw_rsa_keyring_bob ) diff --git a/examples/src/keyrings/required_encryption_context_cmm.py b/examples/src/required_encryption_context_cmm.py similarity index 98% rename from examples/src/keyrings/required_encryption_context_cmm.py rename to examples/src/required_encryption_context_cmm.py index 3f106c5ee..1d5140e6d 100644 --- a/examples/src/keyrings/required_encryption_context_cmm.py +++ b/examples/src/required_encryption_context_cmm.py @@ -19,7 +19,7 @@ CreateRequiredEncryptionContextCMMInput, ) from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring -from typing import Dict, List +from typing import Dict, List # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy @@ -53,7 +53,8 @@ def encrypt_and_decrypt_with_keyring( # Most encrypted data should have an associated encryption context # to protect integrity. This sample uses placeholder values. # For more information see: - # blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management # noqa: E501 + # pylint: disable=line-too-long + # blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management encryption_context: Dict[str, str] = { "key1": "value1", "key2": "value2", diff --git a/examples/src/keyrings/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py similarity index 99% rename from examples/src/keyrings/set_encryption_algorithm_suite_example.py rename to examples/src/set_encryption_algorithm_suite_example.py index c14eb4bb3..200570083 100644 --- a/examples/src/keyrings/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -45,7 +45,7 @@ from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict +from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/test/__init__.py b/examples/test/__init__.py index e8fd618b1..120179eda 100644 --- a/examples/test/__init__.py +++ b/examples/test/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/keyrings/__init__.py b/examples/test/legacy/__init__.py similarity index 100% rename from examples/test/keyrings/__init__.py rename to examples/test/legacy/__init__.py diff --git a/examples/test/examples_test_utils.py b/examples/test/legacy/examples_test_utils.py similarity index 98% rename from examples/test/examples_test_utils.py rename to examples/test/legacy/examples_test_utils.py index 8a51f21c8..afd531cc6 100644 --- a/examples/test/examples_test_utils.py +++ b/examples/test/legacy/examples_test_utils.py @@ -15,7 +15,7 @@ import sys os.environ["AWS_ENCRYPTION_SDK_EXAMPLES_TESTING"] = "yes" -sys.path.extend([os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"])]) +sys.path.extend([os.sep.join([os.path.dirname(__file__), "..", "..", "..", "test", "integration"])]) static_plaintext = ( b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. " diff --git a/examples/test/legacy/pylintrc b/examples/test/legacy/pylintrc new file mode 100644 index 000000000..67090eedf --- /dev/null +++ b/examples/test/legacy/pylintrc @@ -0,0 +1,22 @@ +[MESSAGES CONTROL] +# Disabling messages that we either don't care about for tests or are necessary to break for tests. +disable = + invalid-name, # we prefer long, descriptive, names for tests + missing-docstring, # we don't write docstrings for tests + wrong-import-position, # similar to E0401, pylint does not appear to identify + # unknown modules as non-standard-library. flake8 tests for this as well + # and does treat them properly + duplicate-code, # tests for similar things tend to be similar + consider-using-f-string # disable until 2022-05-05; 6 months after 3.5 deprecation + +[VARIABLES] +additional-builtins = raw_input + +[DESIGN] +max-args = 10 + +[FORMAT] +max-line-length = 120 + +[REPORTS] +msg-template = {path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/examples/test/test_i_basic_encryption.py b/examples/test/legacy/test_i_basic_encryption.py similarity index 94% rename from examples/test/test_i_basic_encryption.py rename to examples/test/legacy/test_i_basic_encryption.py index f2a4fab51..a2a96b08f 100644 --- a/examples/test/test_i_basic_encryption.py +++ b/examples/test/legacy/test_i_basic_encryption.py @@ -14,10 +14,9 @@ import botocore.session import pytest -from ..src.basic_encryption import cycle_string +from ...src.legacy.basic_encryption import cycle_string from .examples_test_utils import get_cmk_arn, static_plaintext - pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py b/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py similarity index 87% rename from examples/test/test_i_basic_file_encryption_with_multiple_providers.py rename to examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py index 282a272ab..af9fb223e 100644 --- a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py +++ b/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py @@ -17,10 +17,8 @@ import botocore.session import pytest -from ..src.basic_file_encryption_with_multiple_providers import cycle_file -from .examples_test_utils import get_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.basic_file_encryption_with_multiple_providers import cycle_file +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py b/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py similarity index 93% rename from examples/test/test_i_basic_file_encryption_with_raw_key_provider.py rename to examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py index 710c0ccac..d4dd0534c 100644 --- a/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py +++ b/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py @@ -16,10 +16,9 @@ import pytest -from ..src.basic_file_encryption_with_raw_key_provider import cycle_file +from ...src.legacy.basic_file_encryption_with_raw_key_provider import cycle_file from .examples_test_utils import static_plaintext - pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_data_key_caching_basic.py b/examples/test/legacy/test_i_data_key_caching_basic.py similarity index 92% rename from examples/test/test_i_data_key_caching_basic.py rename to examples/test/legacy/test_i_data_key_caching_basic.py index 734c35692..960059597 100644 --- a/examples/test/test_i_data_key_caching_basic.py +++ b/examples/test/legacy/test_i_data_key_caching_basic.py @@ -13,10 +13,9 @@ """Unit test suite for the basic data key caching example in the AWS-hosted documentation.""" import pytest -from ..src.data_key_caching_basic import encrypt_with_caching +from ...src.legacy.data_key_caching_basic import encrypt_with_caching from .examples_test_utils import get_cmk_arn - pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_discovery_kms_provider.py b/examples/test/legacy/test_i_discovery_kms_provider.py similarity index 85% rename from examples/test/test_i_discovery_kms_provider.py rename to examples/test/legacy/test_i_discovery_kms_provider.py index e9a1c6e71..09c78fe36 100644 --- a/examples/test/test_i_discovery_kms_provider.py +++ b/examples/test/legacy/test_i_discovery_kms_provider.py @@ -15,10 +15,8 @@ import botocore.session import pytest -from ..src.discovery_kms_provider import encrypt_decrypt -from .examples_test_utils import get_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.discovery_kms_provider import encrypt_decrypt +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_mrk_aware_kms_provider.py b/examples/test/legacy/test_i_mrk_aware_kms_provider.py similarity index 90% rename from examples/test/test_i_mrk_aware_kms_provider.py rename to examples/test/legacy/test_i_mrk_aware_kms_provider.py index 8e7a003f8..81cd5cfd2 100644 --- a/examples/test/test_i_mrk_aware_kms_provider.py +++ b/examples/test/legacy/test_i_mrk_aware_kms_provider.py @@ -14,10 +14,8 @@ import pytest -from ..src.mrk_aware_kms_provider import encrypt_decrypt -from .examples_test_utils import get_mrk_arn, get_second_mrk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.mrk_aware_kms_provider import encrypt_decrypt +from .examples_test_utils import get_mrk_arn, get_second_mrk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_multiple_kms_cmk.py b/examples/test/legacy/test_i_multiple_kms_cmk.py similarity index 90% rename from examples/test/test_i_multiple_kms_cmk.py rename to examples/test/legacy/test_i_multiple_kms_cmk.py index 39369cbc6..f2ecac660 100644 --- a/examples/test/test_i_multiple_kms_cmk.py +++ b/examples/test/legacy/test_i_multiple_kms_cmk.py @@ -15,10 +15,8 @@ import botocore.session import pytest -from ..src.multiple_kms_cmk import encrypt_decrypt -from .examples_test_utils import get_cmk_arn, get_second_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.multiple_kms_cmk import encrypt_decrypt +from .examples_test_utils import get_cmk_arn, get_second_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_one_kms_cmk.py b/examples/test/legacy/test_i_one_kms_cmk.py similarity index 86% rename from examples/test/test_i_one_kms_cmk.py rename to examples/test/legacy/test_i_one_kms_cmk.py index 71ce74d3d..a8d083e67 100644 --- a/examples/test/test_i_one_kms_cmk.py +++ b/examples/test/legacy/test_i_one_kms_cmk.py @@ -15,10 +15,8 @@ import botocore.session import pytest -from ..src.one_kms_cmk import encrypt_decrypt -from .examples_test_utils import get_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.one_kms_cmk import encrypt_decrypt +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_one_kms_cmk_streaming_data.py b/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py similarity index 94% rename from examples/test/test_i_one_kms_cmk_streaming_data.py rename to examples/test/legacy/test_i_one_kms_cmk_streaming_data.py index b22fa4232..6115ed567 100644 --- a/examples/test/test_i_one_kms_cmk_streaming_data.py +++ b/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py @@ -17,10 +17,9 @@ import botocore.session import pytest -from ..src.one_kms_cmk_streaming_data import encrypt_decrypt_stream +from ...src.legacy.one_kms_cmk_streaming_data import encrypt_decrypt_stream from .examples_test_utils import get_cmk_arn, static_plaintext - pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_one_kms_cmk_unsigned.py b/examples/test/legacy/test_i_one_kms_cmk_unsigned.py similarity index 86% rename from examples/test/test_i_one_kms_cmk_unsigned.py rename to examples/test/legacy/test_i_one_kms_cmk_unsigned.py index 8a2758c96..cc9acd949 100644 --- a/examples/test/test_i_one_kms_cmk_unsigned.py +++ b/examples/test/legacy/test_i_one_kms_cmk_unsigned.py @@ -15,10 +15,8 @@ import botocore.session import pytest -from ..src.one_kms_cmk_unsigned import encrypt_decrypt -from .examples_test_utils import get_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.one_kms_cmk_unsigned import encrypt_decrypt +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_set_commitment.py b/examples/test/legacy/test_i_set_commitment.py similarity index 86% rename from examples/test/test_i_set_commitment.py rename to examples/test/legacy/test_i_set_commitment.py index 96247334b..7f86fdcc2 100644 --- a/examples/test/test_i_set_commitment.py +++ b/examples/test/legacy/test_i_set_commitment.py @@ -15,10 +15,8 @@ import botocore.session import pytest -from ..src.set_commitment import encrypt_decrypt -from .examples_test_utils import get_cmk_arn -from .examples_test_utils import static_plaintext - +from ...src.legacy.set_commitment import encrypt_decrypt +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] diff --git a/examples/test/pylintrc b/examples/test/pylintrc index 67090eedf..9792ea592 100644 --- a/examples/test/pylintrc +++ b/examples/test/pylintrc @@ -1,6 +1,7 @@ [MESSAGES CONTROL] # Disabling messages that we either don't care about for tests or are necessary to break for tests. disable = + import-error, # ignore mpl import errors invalid-name, # we prefer long, descriptive, names for tests missing-docstring, # we don't write docstrings for tests wrong-import-position, # similar to E0401, pylint does not appear to identify diff --git a/examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py b/examples/test/test_i_aws_kms_discovery_keyring_example.py similarity index 86% rename from examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py rename to examples/test/test_i_aws_kms_discovery_keyring_example.py index af3c2a3a3..06b141712 100644 --- a/examples/test/keyrings/test_i_aws_kms_discovery_keyring_example.py +++ b/examples/test/test_i_aws_kms_discovery_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS Discovery keyring example.""" import pytest -from ...src.keyrings.aws_kms_discovery_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_discovery_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py b/examples/test/test_i_aws_kms_discovery_multi_keyring_example.py similarity index 86% rename from examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py rename to examples/test/test_i_aws_kms_discovery_multi_keyring_example.py index eff2a1a3b..f8cd13550 100644 --- a/examples/test/keyrings/test_i_aws_kms_discovery_multi_keyring_example.py +++ b/examples/test/test_i_aws_kms_discovery_multi_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS Discovery Multi keyring example.""" import pytest -from ...src.keyrings.aws_kms_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_keyring_example.py b/examples/test/test_i_aws_kms_keyring_example.py similarity index 85% rename from examples/test/keyrings/test_i_aws_kms_keyring_example.py rename to examples/test/test_i_aws_kms_keyring_example.py index 83a784a9e..ef7b1b643 100644 --- a/examples/test/keyrings/test_i_aws_kms_keyring_example.py +++ b/examples/test/test_i_aws_kms_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS keyring example.""" import pytest -from ...src.keyrings.aws_kms_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py b/examples/test/test_i_aws_kms_mrk_discovery_keyring_example.py similarity index 89% rename from examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py rename to examples/test/test_i_aws_kms_mrk_discovery_keyring_example.py index bc0279066..0a49709a3 100644 --- a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_keyring_example.py +++ b/examples/test/test_i_aws_kms_mrk_discovery_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS MRK Discovery keyring example.""" import pytest -from ...src.keyrings.aws_kms_mrk_discovery_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_mrk_discovery_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py b/examples/test/test_i_aws_kms_mrk_discovery_multi_keyring_example.py similarity index 88% rename from examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py rename to examples/test/test_i_aws_kms_mrk_discovery_multi_keyring_example.py index 93672b046..ded9a78e8 100644 --- a/examples/test/keyrings/test_i_aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/test/test_i_aws_kms_mrk_discovery_multi_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS MRK Discovery Multi keyring example.""" import pytest -from ...src.keyrings.aws_kms_mrk_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_mrk_discovery_multi_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py b/examples/test/test_i_aws_kms_mrk_keyring_example.py similarity index 91% rename from examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py rename to examples/test/test_i_aws_kms_mrk_keyring_example.py index ab81d9c10..3bc977e26 100644 --- a/examples/test/keyrings/test_i_aws_kms_mrk_keyring_example.py +++ b/examples/test/test_i_aws_kms_mrk_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS MRK keyring example.""" import pytest -from ...src.keyrings.aws_kms_mrk_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_mrk_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py b/examples/test/test_i_aws_kms_mrk_multi_keyring_example.py similarity index 90% rename from examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py rename to examples/test/test_i_aws_kms_mrk_multi_keyring_example.py index 8272f3987..960a8f3cb 100644 --- a/examples/test/keyrings/test_i_aws_kms_mrk_multi_keyring_example.py +++ b/examples/test/test_i_aws_kms_mrk_multi_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS MRK Multi keyring example.""" import pytest -from ...src.keyrings.aws_kms_mrk_multi_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_mrk_multi_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py b/examples/test/test_i_aws_kms_multi_keyring_example.py similarity index 90% rename from examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py rename to examples/test/test_i_aws_kms_multi_keyring_example.py index 10f991754..28cf0c497 100644 --- a/examples/test/keyrings/test_i_aws_kms_multi_keyring_example.py +++ b/examples/test/test_i_aws_kms_multi_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS multi keyring example.""" import pytest -from ...src.keyrings.aws_kms_multi_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_multi_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py b/examples/test/test_i_aws_kms_rsa_keyring_example.py similarity index 93% rename from examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py rename to examples/test/test_i_aws_kms_rsa_keyring_example.py index 4d953947a..6f41da1cb 100644 --- a/examples/test/keyrings/test_i_aws_kms_rsa_keyring_example.py +++ b/examples/test/test_i_aws_kms_rsa_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the AWS KMS RSA keyring example.""" import pytest -from ...src.keyrings.aws_kms_rsa_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.aws_kms_rsa_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_file_streaming_example.py b/examples/test/test_i_file_streaming_example.py similarity index 97% rename from examples/test/keyrings/test_i_file_streaming_example.py rename to examples/test/test_i_file_streaming_example.py index 2e502f185..67cd2b34c 100644 --- a/examples/test/keyrings/test_i_file_streaming_example.py +++ b/examples/test/test_i_file_streaming_example.py @@ -5,7 +5,7 @@ import pytest -from ...src.keyrings.file_streaming_example import encrypt_and_decrypt_with_keyring +from ..src.file_streaming_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_hierarchical_keyring_example.py b/examples/test/test_i_hierarchical_keyring_example.py similarity index 86% rename from examples/test/keyrings/test_i_hierarchical_keyring_example.py rename to examples/test/test_i_hierarchical_keyring_example.py index 6b3f3850a..72f2d48df 100644 --- a/examples/test/keyrings/test_i_hierarchical_keyring_example.py +++ b/examples/test/test_i_hierarchical_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the hierarchical keyring example.""" import pytest -from ...src.keyrings.hierarchical_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.hierarchical_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_migration_set_commitment_policy_example.py b/examples/test/test_i_migration_set_commitment_policy_example.py similarity index 83% rename from examples/test/keyrings/test_i_migration_set_commitment_policy_example.py rename to examples/test/test_i_migration_set_commitment_policy_example.py index 7580ed670..afbc758bc 100644 --- a/examples/test/keyrings/test_i_migration_set_commitment_policy_example.py +++ b/examples/test/test_i_migration_set_commitment_policy_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_set_commitment_policy_example.""" import pytest -from ...src.keyrings.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring +from ..src.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_multi_keyring_example.py b/examples/test/test_i_multi_keyring_example.py similarity index 85% rename from examples/test/keyrings/test_i_multi_keyring_example.py rename to examples/test/test_i_multi_keyring_example.py index ad12c0c9c..485789c8b 100644 --- a/examples/test/keyrings/test_i_multi_keyring_example.py +++ b/examples/test/test_i_multi_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the multi keyring example.""" import pytest -from ...src.keyrings.multi_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.multi_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_raw_aes_keyring_example.py b/examples/test/test_i_raw_aes_keyring_example.py similarity index 81% rename from examples/test/keyrings/test_i_raw_aes_keyring_example.py rename to examples/test/test_i_raw_aes_keyring_example.py index e5bd6d4c2..5ac2b6012 100644 --- a/examples/test/keyrings/test_i_raw_aes_keyring_example.py +++ b/examples/test/test_i_raw_aes_keyring_example.py @@ -3,7 +3,7 @@ """Test suite for the Raw AES keyring example.""" import pytest -from ...src.keyrings.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring +from ..src.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_raw_rsa_keyring_example.py b/examples/test/test_i_raw_rsa_keyring_example.py similarity index 93% rename from examples/test/keyrings/test_i_raw_rsa_keyring_example.py rename to examples/test/test_i_raw_rsa_keyring_example.py index 87786b4b3..8cdf628f2 100644 --- a/examples/test/keyrings/test_i_raw_rsa_keyring_example.py +++ b/examples/test/test_i_raw_rsa_keyring_example.py @@ -5,7 +5,7 @@ import pytest -from ...src.keyrings.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring, generate_rsa_keys +from ..src.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring, generate_rsa_keys pytestmark = [pytest.mark.examples] @@ -60,7 +60,7 @@ def test_encrypt_and_decrypt_fails_if_user_provides_only_public_key(): test both encryption and decryption, or not provide any keys and the example generates both """ # Generate the user keys for testing - user_public_key, user_private_key = generate_rsa_keys() + user_public_key, user_private_key = generate_rsa_keys() # pylint: disable=unused-variable # Convert the public key to string user_public_key = user_public_key.decode('utf-8') @@ -92,7 +92,7 @@ def test_encrypt_and_decrypt_fails_if_user_provides_only_private_key(): test both encryption and decryption, or not provide any keys and the example generates both """ # Generate the user keys for testing - user_public_key, user_private_key = generate_rsa_keys() + user_public_key, user_private_key = generate_rsa_keys() # pylint: disable=unused-variable # Convert the private key to string user_private_key = user_private_key.decode('utf-8') diff --git a/examples/test/keyrings/test_i_required_encryption_context_cmm.py b/examples/test/test_i_required_encryption_context_cmm.py similarity index 81% rename from examples/test/keyrings/test_i_required_encryption_context_cmm.py rename to examples/test/test_i_required_encryption_context_cmm.py index 724705faa..2aa702b37 100644 --- a/examples/test/keyrings/test_i_required_encryption_context_cmm.py +++ b/examples/test/test_i_required_encryption_context_cmm.py @@ -3,7 +3,7 @@ """Test suite for the required encryption context CMM example.""" import pytest -from ...src.keyrings.required_encryption_context_cmm import encrypt_and_decrypt_with_keyring +from ..src.required_encryption_context_cmm import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py b/examples/test/test_i_set_encryption_algorithm_suite_example.py similarity index 79% rename from examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py rename to examples/test/test_i_set_encryption_algorithm_suite_example.py index 0703bc961..9069cfe44 100644 --- a/examples/test/keyrings/test_i_set_encryption_algorithm_suite_example.py +++ b/examples/test/test_i_set_encryption_algorithm_suite_example.py @@ -3,7 +3,7 @@ """Test suite for the Set Algorithm Suite example for a Raw AES keyring.""" import pytest -from ...src.keyrings.set_encryption_algorithm_suite_example import encrypt_and_decrypt_with_keyring +from ..src.set_encryption_algorithm_suite_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/tox.ini b/tox.ini index 6a4c3d10c..8d4af1d2d 100644 --- a/tox.ini +++ b/tox.ini @@ -89,10 +89,10 @@ commands = mpllocal: {[testenv:base-command]commands} test/ -m local integ: {[testenv:base-command]commands} test/ -m integ --ignore test/mpl/ accept: {[testenv:base-command]commands} test/ -m accept --ignore test/mpl/ - examples: {[testenv:base-command]commands} examples/test/ -m examples --ignore examples/test/keyrings/ + examples: {[testenv:base-command]commands} examples/test/legacy/ -m examples # MPL keyring examples require a special IAM role; run these separately under a separate set of permissions - mplexamples: {[testenv:base-command]commands} examples/test/keyrings -m examples - all: {[testenv:base-command]commands} test/ examples/test/ --ignore test/mpl/ --ignore examples/test/keyrings/ + mplexamples: {[testenv:base-command]commands} examples/test/ -m examples --ignore examples/test/legacy/ + all: {[testenv:base-command]commands} test/ examples/test/legacy/ --ignore test/mpl/ mplall: {[testenv:base-command]commands} test/ examples/test/ manual: {[testenv:base-command]commands} @@ -192,8 +192,8 @@ commands = basepython = {[testenv:pylint]basepython} deps = {[testenv:pylint]deps} commands = - pylint --rcfile=examples/src/pylintrc examples/src/ --ignore-paths=examples/src/keyrings - pylint --rcfile=examples/test/pylintrc --disable R0801 examples/test/ --ignore-paths=examples/test/keyrings + pylint --rcfile=examples/src/pylintrc examples/src/ + pylint --rcfile=examples/test/pylintrc --disable R0801 examples/test/ [testenv:pylint-tests] basepython = {[testenv:pylint]basepython} From bd32c79497df7ccd788490a83c5c4a33f10dd00e Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 20 May 2024 14:15:51 -0700 Subject: [PATCH 12/51] chore: Sync from master (#682) --- .github/workflows/ci_tests.yaml | 1 - README.rst | 2 +- buildspec.yml | 38 ------------------- codebuild/py37/awses_local.yml | 25 ------------ codebuild/py37/examples.yml | 22 ----------- codebuild/py37/integ.yml | 22 ----------- decrypt_oracle/app.py | 14 +------ decrypt_oracle/setup.py | 1 - .../__init__.py | 14 +------ .../aws_encryption_sdk_decrypt_oracle/app.py | 14 +------ .../key_providers/__init__.py | 14 +------ .../key_providers/counting.py | 14 +------ .../key_providers/null.py | 14 +------ decrypt_oracle/test/__init__.py | 14 +------ decrypt_oracle/test/integration/__init__.py | 14 +------ .../integration/integration_test_utils.py | 14 +------ .../test/integration/test_i_decrypt_oracle.py | 14 +------ .../test/test_n_generate_test_vectors.py | 14 +------ decrypt_oracle/test/unit/__init__.py | 14 +------ .../test/unit/key_providers/__init__.py | 14 +------ .../unit/key_providers/test_u_counting.py | 14 +------ .../test/unit/key_providers/test_u_null.py | 14 +------ examples/__init__.py | 14 +------ examples/src/legacy/basic_encryption.py | 14 +------ ...file_encryption_with_multiple_providers.py | 14 +------ ...c_file_encryption_with_raw_key_provider.py | 14 +------ .../custom_kms_client_for_kms_provider.py | 14 +------ examples/src/legacy/data_key_caching_basic.py | 14 +------ examples/src/legacy/discovery_kms_provider.py | 14 +------ examples/src/legacy/mrk_aware_kms_provider.py | 14 +------ examples/src/legacy/multiple_kms_cmk.py | 14 +------ examples/src/legacy/one_kms_cmk.py | 14 +------ .../src/legacy/one_kms_cmk_streaming_data.py | 14 +------ examples/src/legacy/one_kms_cmk_unsigned.py | 14 +------ examples/src/legacy/set_commitment.py | 14 +------ examples/test/legacy/examples_test_utils.py | 14 +------ .../test/legacy/test_i_basic_encryption.py | 14 +------ ...file_encryption_with_multiple_providers.py | 14 +------ ...c_file_encryption_with_raw_key_provider.py | 14 +------ .../legacy/test_i_data_key_caching_basic.py | 14 +------ .../legacy/test_i_discovery_kms_provider.py | 14 +------ .../legacy/test_i_mrk_aware_kms_provider.py | 14 +------ .../test/legacy/test_i_multiple_kms_cmk.py | 14 +------ examples/test/legacy/test_i_one_kms_cmk.py | 14 +------ .../test_i_one_kms_cmk_streaming_data.py | 14 +------ .../legacy/test_i_one_kms_cmk_unsigned.py | 14 +------ examples/test/legacy/test_i_set_commitment.py | 14 +------ setup.py | 2 +- src/aws_encryption_sdk/__init__.py | 14 +------ src/aws_encryption_sdk/caches/__init__.py | 14 +------ src/aws_encryption_sdk/caches/base.py | 14 +------ src/aws_encryption_sdk/caches/local.py | 14 +------ src/aws_encryption_sdk/caches/null.py | 14 +------ src/aws_encryption_sdk/compatability.py | 17 ++------- src/aws_encryption_sdk/exceptions.py | 14 +------ src/aws_encryption_sdk/identifiers.py | 14 +------ src/aws_encryption_sdk/internal/__init__.py | 14 +------ src/aws_encryption_sdk/internal/arn.py | 14 +------ .../internal/crypto/__init__.py | 14 +------ .../internal/crypto/authentication.py | 14 +------ .../internal/crypto/data_keys.py | 14 +------ .../internal/crypto/elliptic_curve.py | 14 +------ .../internal/crypto/encryption.py | 14 +------ src/aws_encryption_sdk/internal/crypto/iv.py | 14 +------ .../internal/crypto/wrapping_keys.py | 14 +------ src/aws_encryption_sdk/internal/defaults.py | 14 +------ .../internal/formatting/__init__.py | 14 +------ .../internal/formatting/deserialize.py | 14 +------ .../internal/formatting/encryption_context.py | 14 +------ .../internal/formatting/serialize.py | 14 +------ src/aws_encryption_sdk/internal/str_ops.py | 14 +------ src/aws_encryption_sdk/internal/structures.py | 14 +------ .../internal/utils/__init__.py | 14 +------ .../internal/utils/commitment.py | 14 +------ .../internal/utils/signature.py | 14 +------ .../internal/utils/streams.py | 14 +------ .../key_providers/__init__.py | 14 +------ src/aws_encryption_sdk/key_providers/base.py | 14 +------ src/aws_encryption_sdk/key_providers/kms.py | 14 +------ src/aws_encryption_sdk/key_providers/raw.py | 14 +------ .../materials_managers/__init__.py | 14 +------ .../materials_managers/base.py | 14 +------ .../materials_managers/caching.py | 14 +------ .../materials_managers/default.py | 14 +------ src/aws_encryption_sdk/streaming_client.py | 14 +------ src/aws_encryption_sdk/structures.py | 14 +------ test/__init__.py | 14 +------ test/functional/__init__.py | 14 +------ test/functional/key_providers/__init__.py | 14 +------ test/functional/key_providers/test_base.py | 14 +------ .../test_f_aws_encryption_sdk_client.py | 14 +------ test/functional/test_f_commitment.py | 14 +------ test/functional/test_f_crypto.py | 14 +------ test/functional/test_f_crypto_iv.py | 14 +------ test/functional/test_f_xcompat.py | 14 +------ test/integration/__init__.py | 14 +------ test/integration/integration_test_utils.py | 14 +------ .../test_i_aws_encrytion_sdk_client.py | 14 +------ test/integration/test_i_thread_safety.py | 14 +------ test/integration/test_i_xcompat_kms.py | 14 +------ test/integration/test_kat_commitment.py | 14 +------ test/unit/__init__.py | 14 +------ test/unit/test_algorithm_suite.py | 14 +------ test/unit/test_arn.py | 14 +------ test/unit/test_caches.py | 14 +------ test/unit/test_caches_base.py | 14 +------ test/unit/test_caches_crypto_cache_entry.py | 14 +------ test/unit/test_caches_local.py | 14 +------ test/unit/test_caches_null.py | 14 +------ test/unit/test_commitment.py | 14 +------ test/unit/test_compatability.py | 14 +------ test/unit/test_crypto.py | 14 +------ .../unit/test_crypto_authentication_signer.py | 14 +------ .../test_crypto_authentication_verifier.py | 14 +------ test/unit/test_crypto_data_keys.py | 14 +------ test/unit/test_crypto_elliptic_curve.py | 14 +------ test/unit/test_crypto_encryption_decryptor.py | 14 +------ test/unit/test_crypto_encryption_encryptor.py | 14 +------ .../test_crypto_prehashing_authenticator.py | 14 +------ test/unit/test_crypto_wrapping_keys.py | 14 +------ test/unit/test_defaults.py | 14 +------ test/unit/test_deserialize.py | 14 +------ test/unit/test_encryption_client.py | 14 +------ test/unit/test_encryption_context.py | 14 +------ test/unit/test_identifiers.py | 14 +------ test/unit/test_internal_structures.py | 14 +------ test/unit/test_material_managers.py | 14 +------ test/unit/test_material_managers_base.py | 14 +------ test/unit/test_material_managers_caching.py | 14 +------ test/unit/test_material_managers_default.py | 14 +------ test/unit/test_providers_base_master_key.py | 14 +------ .../test_providers_base_master_key_config.py | 14 +------ ...test_providers_base_master_key_provider.py | 14 +------ ...oviders_base_master_key_provider_config.py | 14 +------ test/unit/test_providers_kms_master_key.py | 14 +------ .../test_providers_kms_master_key_config.py | 14 +------ .../test_providers_kms_master_key_provider.py | 14 +------ ...roviders_kms_master_key_provider_config.py | 14 +------ test/unit/test_providers_raw_master_key.py | 14 +------ .../test_providers_raw_master_key_config.py | 14 +------ .../test_providers_raw_master_key_provider.py | 14 +------ test/unit/test_serialize.py | 14 +------ test/unit/test_streaming_client_configs.py | 14 +------ ...test_streaming_client_encryption_stream.py | 14 +------ .../test_streaming_client_stream_decryptor.py | 14 +------ .../test_streaming_client_stream_encryptor.py | 14 +------ test/unit/test_structures.py | 14 +------ test/unit/test_util_str_ops.py | 14 +------ test/unit/test_util_streams.py | 14 +------ test/unit/test_utils.py | 14 +------ test/unit/test_values.py | 14 +------ test/unit/unit_test_utils.py | 14 +------ test_vector_handlers/README.rst | 2 +- test_vector_handlers/setup.py | 1 - .../src/awses_test_vectors/__init__.py | 14 +------ .../awses_test_vectors/commands/__init__.py | 14 +------ .../commands/full_message_decrypt.py | 14 +------ .../commands/full_message_decrypt_generate.py | 14 +------ .../commands/full_message_encrypt.py | 14 +------ .../awses_test_vectors/internal/__init__.py | 14 +------ .../awses_test_vectors/internal/aws_kms.py | 14 +------ .../awses_test_vectors/internal/defaults.py | 14 +------ .../awses_test_vectors/internal/mypy_types.py | 14 +------ .../src/awses_test_vectors/internal/util.py | 14 +------ .../awses_test_vectors/manifests/__init__.py | 14 +------ .../manifests/full_message/__init__.py | 14 +------ .../manifests/full_message/decrypt.py | 14 +------ .../full_message/decrypt_generation.py | 14 +------ .../manifests/full_message/encrypt.py | 14 +------ .../src/awses_test_vectors/manifests/keys.py | 14 +------ .../manifests/master_key.py | 14 +------ .../aws-crypto-tools-test-vector-framework | 2 +- .../commands/test_i_full_message_encrypt.py | 14 +------ .../integration/integration_test_utils.py | 14 +------ tox.ini | 2 +- 175 files changed, 333 insertions(+), 2072 deletions(-) delete mode 100644 codebuild/py37/awses_local.yml delete mode 100644 codebuild/py37/examples.yml delete mode 100644 codebuild/py37/integ.yml diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index b03c47163..7ec273ba2 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -32,7 +32,6 @@ jobs: # - windows-latest - macos-12 python: - - 3.7 - 3.8 - 3.9 - "3.10" diff --git a/README.rst b/README.rst index c21b7a0b3..6cd8c6824 100644 --- a/README.rst +++ b/README.rst @@ -34,7 +34,7 @@ Getting Started Required Prerequisites ====================== -* Python 3.7+ +* Python 3.8+ * cryptography >= 3.4.6 * boto3 >= 1.10.0 * attrs diff --git a/buildspec.yml b/buildspec.yml index 873e5941e..086743dbc 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -4,44 +4,6 @@ batch: fast-fail: false build-graph: - # 3.7 - - identifier: py37_integ - buildspec: codebuild/py37/integ.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_examples - buildspec: codebuild/py37/examples.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_decrypt_dafny_esdk_vectors - buildspec: codebuild/py37/decrypt_dafny_esdk_vectors.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_decrypt_net_401_vectors - buildspec: codebuild/py37/decrypt_net_401_vectors.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_encrypt_masterkey - buildspec: codebuild/py37/encrypt_masterkey.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_generate_decrypt_vectors_masterkey - buildspec: codebuild/py37/generate_decrypt_vectors_masterkey.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_decrypt_masterkey_with_masterkey - depend-on: - - py37_generate_decrypt_vectors_masterkey - buildspec: codebuild/py37/decrypt_masterkey_with_masterkey.yml - env: - image: aws/codebuild/standard:5.0 - - identifier: py37_decrypt_masterkey_with_js - depend-on: - - py37_generate_decrypt_vectors_masterkey - buildspec: codebuild/py37/decrypt_masterkey_with_js.yml - env: - image: aws/codebuild/standard:5.0 - # 3.8 - identifier: py38_integ buildspec: codebuild/py38/integ.yml diff --git a/codebuild/py37/awses_local.yml b/codebuild/py37/awses_local.yml deleted file mode 100644 index 02dfe5d0b..000000000 --- a/codebuild/py37/awses_local.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-awses_local" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_API_DEPLOYMENT_ID: "xi1mwx3ttb" - AWS_ENCRYPTION_SDK_PYTHON_DECRYPT_ORACLE_REGION: "us-west-2" - -phases: - install: - runtime-versions: - python: 3.7 - build: - commands: - - pip install "tox < 4.0" - - cd test_vector_handlers - - tox diff --git a/codebuild/py37/examples.yml b/codebuild/py37/examples.yml deleted file mode 100644 index 0b240c768..000000000 --- a/codebuild/py37/examples.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-examples" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - build: - commands: - - pip install "tox < 4.0" - - tox diff --git a/codebuild/py37/integ.yml b/codebuild/py37/integ.yml deleted file mode 100644 index b702d45cb..000000000 --- a/codebuild/py37/integ.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-integ" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - build: - commands: - - pip install "tox < 4.0" - - tox diff --git a/decrypt_oracle/app.py b/decrypt_oracle/app.py index 450fd25d0..a36b6db97 100644 --- a/decrypt_oracle/app.py +++ b/decrypt_oracle/app.py @@ -1,14 +1,4 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Shim to pull decryption oracle app into expected location for Chalice.""" from aws_encryption_sdk_decrypt_oracle.app import APP as app # noqa pylint: disable=unused-import diff --git a/decrypt_oracle/setup.py b/decrypt_oracle/setup.py index f68454392..9908944ef 100644 --- a/decrypt_oracle/setup.py +++ b/decrypt_oracle/setup.py @@ -45,7 +45,6 @@ def get_requirements(): "Natural Language :: English", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", diff --git a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/__init__.py b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/__init__.py index 6a8068ecc..1210013e3 100644 --- a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/__init__.py +++ b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/__init__.py @@ -1,14 +1,4 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Decrypt Oracle using the AWS Encryption SDK for Python.""" __version__ = "0.0.1" diff --git a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/app.py b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/app.py index 820b9e015..1294fe5d1 100644 --- a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/app.py +++ b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/app.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Decrypt Oracle powered by the AWS Encryption SDK for Python.""" import json import logging diff --git a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/__init__.py b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/__init__.py index 98889fd63..c384ec142 100644 --- a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/__init__.py +++ b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Special key providers for use by the decrypt oracle.""" diff --git a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/counting.py b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/counting.py index da6c74cfc..cc2b5377f 100644 --- a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/counting.py +++ b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/counting.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Master key that generates deterministic data keys and decrypts a pre-defined encrypted data key value to that deterministic data keys. diff --git a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/null.py b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/null.py index 3eb90b3b9..2a90bc6e5 100644 --- a/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/null.py +++ b/decrypt_oracle/src/aws_encryption_sdk_decrypt_oracle/key_providers/null.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Master key that provides null data keys.""" from typing import Dict, NoReturn, Text diff --git a/decrypt_oracle/test/__init__.py b/decrypt_oracle/test/__init__.py index 2add15ef3..d548f9b1f 100644 --- a/decrypt_oracle/test/__init__.py +++ b/decrypt_oracle/test/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Dummy stub to make linters work better.""" diff --git a/decrypt_oracle/test/integration/__init__.py b/decrypt_oracle/test/integration/__init__.py index 2add15ef3..d548f9b1f 100644 --- a/decrypt_oracle/test/integration/__init__.py +++ b/decrypt_oracle/test/integration/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Dummy stub to make linters work better.""" diff --git a/decrypt_oracle/test/integration/integration_test_utils.py b/decrypt_oracle/test/integration/integration_test_utils.py index c03b7f440..0989e5022 100644 --- a/decrypt_oracle/test/integration/integration_test_utils.py +++ b/decrypt_oracle/test/integration/integration_test_utils.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper utilities for use by integration tests.""" import base64 import json diff --git a/decrypt_oracle/test/integration/test_i_decrypt_oracle.py b/decrypt_oracle/test/integration/test_i_decrypt_oracle.py index 5863ecc0e..0ed733afb 100644 --- a/decrypt_oracle/test/integration/test_i_decrypt_oracle.py +++ b/decrypt_oracle/test/integration/test_i_decrypt_oracle.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Integration tests for deployed API.""" import pytest import requests diff --git a/decrypt_oracle/test/test_n_generate_test_vectors.py b/decrypt_oracle/test/test_n_generate_test_vectors.py index deb3f7c4d..6e35a0267 100644 --- a/decrypt_oracle/test/test_n_generate_test_vectors.py +++ b/decrypt_oracle/test/test_n_generate_test_vectors.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Generate test vectors for use in testing the decrypt oracle.""" import base64 import binascii diff --git a/decrypt_oracle/test/unit/__init__.py b/decrypt_oracle/test/unit/__init__.py index 2add15ef3..d548f9b1f 100644 --- a/decrypt_oracle/test/unit/__init__.py +++ b/decrypt_oracle/test/unit/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Dummy stub to make linters work better.""" diff --git a/decrypt_oracle/test/unit/key_providers/__init__.py b/decrypt_oracle/test/unit/key_providers/__init__.py index 2add15ef3..d548f9b1f 100644 --- a/decrypt_oracle/test/unit/key_providers/__init__.py +++ b/decrypt_oracle/test/unit/key_providers/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Dummy stub to make linters work better.""" diff --git a/decrypt_oracle/test/unit/key_providers/test_u_counting.py b/decrypt_oracle/test/unit/key_providers/test_u_counting.py index ebeaee198..161ef91a2 100644 --- a/decrypt_oracle/test/unit/key_providers/test_u_counting.py +++ b/decrypt_oracle/test/unit/key_providers/test_u_counting.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test for ``aws_encryption_sdk_decrypt_oracle.key_providers.counting``.""" import pytest from aws_encryption_sdk_decrypt_oracle.key_providers.counting import CountingMasterKey diff --git a/decrypt_oracle/test/unit/key_providers/test_u_null.py b/decrypt_oracle/test/unit/key_providers/test_u_null.py index 4c3a2e4d7..be3bb8b0c 100644 --- a/decrypt_oracle/test/unit/key_providers/test_u_null.py +++ b/decrypt_oracle/test/unit/key_providers/test_u_null.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test for ``aws_encryption_sdk_decrypt_oracle.key_providers.null``.""" import pytest from aws_encryption_sdk_decrypt_oracle.key_providers.null import NullMasterKey diff --git a/examples/__init__.py b/examples/__init__.py index 9cef784c2..fa977e22f 100644 --- a/examples/__init__.py +++ b/examples/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Stub to allow relative imports of examples from tests.""" diff --git a/examples/src/legacy/basic_encryption.py b/examples/src/legacy/basic_encryption.py index cfe8ac791..24c667db9 100644 --- a/examples/src/legacy/basic_encryption.py +++ b/examples/src/legacy/basic_encryption.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing basic encryption and decryption of a value already in memory.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/legacy/basic_file_encryption_with_multiple_providers.py b/examples/src/legacy/basic_file_encryption_with_multiple_providers.py index 6a1b7ccd1..f5eb743e5 100644 --- a/examples/src/legacy/basic_file_encryption_with_multiple_providers.py +++ b/examples/src/legacy/basic_file_encryption_with_multiple_providers.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing creation of a RawMasterKeyProvider, how to use multiple master key providers to encrypt, and demonstrating that each master key provider can then be used independently to decrypt the same encrypted message. diff --git a/examples/src/legacy/basic_file_encryption_with_raw_key_provider.py b/examples/src/legacy/basic_file_encryption_with_raw_key_provider.py index 2d964c7b4..28b097f8b 100644 --- a/examples/src/legacy/basic_file_encryption_with_raw_key_provider.py +++ b/examples/src/legacy/basic_file_encryption_with_raw_key_provider.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing creation and use of a RawMasterKeyProvider.""" import filecmp import os diff --git a/examples/src/legacy/custom_kms_client_for_kms_provider.py b/examples/src/legacy/custom_kms_client_for_kms_provider.py index d7658ffaa..07107af1a 100644 --- a/examples/src/legacy/custom_kms_client_for_kms_provider.py +++ b/examples/src/legacy/custom_kms_client_for_kms_provider.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing how to customize the AWS KMS Client.""" import boto3 from botocore.config import Config diff --git a/examples/src/legacy/data_key_caching_basic.py b/examples/src/legacy/data_key_caching_basic.py index e67b35d0a..50567aa58 100644 --- a/examples/src/legacy/data_key_caching_basic.py +++ b/examples/src/legacy/data_key_caching_basic.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example of encryption with data key caching.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/legacy/discovery_kms_provider.py b/examples/src/legacy/discovery_kms_provider.py index 659d76ea6..e5b1683e0 100644 --- a/examples/src/legacy/discovery_kms_provider.py +++ b/examples/src/legacy/discovery_kms_provider.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing encryption of a value already in memory using one KMS CMK, then decryption of the ciphertext using a DiscoveryAwsKmsMasterKeyProvider. """ diff --git a/examples/src/legacy/mrk_aware_kms_provider.py b/examples/src/legacy/mrk_aware_kms_provider.py index da04c7d62..8010872e1 100644 --- a/examples/src/legacy/mrk_aware_kms_provider.py +++ b/examples/src/legacy/mrk_aware_kms_provider.py @@ -1,15 +1,5 @@ -# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing encryption of a value already in memory using one KMS CMK, then decryption of the ciphertext using a DiscoveryAwsKmsMasterKeyProvider. """ diff --git a/examples/src/legacy/multiple_kms_cmk.py b/examples/src/legacy/multiple_kms_cmk.py index 03eef88ae..ee6198819 100644 --- a/examples/src/legacy/multiple_kms_cmk.py +++ b/examples/src/legacy/multiple_kms_cmk.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing basic encryption and decryption of a value already in memory using one KMS CMK.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/legacy/one_kms_cmk.py b/examples/src/legacy/one_kms_cmk.py index cbd28c10a..c7268c6e2 100644 --- a/examples/src/legacy/one_kms_cmk.py +++ b/examples/src/legacy/one_kms_cmk.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing basic encryption and decryption of a value already in memory using one KMS CMK.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy diff --git a/examples/src/legacy/one_kms_cmk_streaming_data.py b/examples/src/legacy/one_kms_cmk_streaming_data.py index f4e5ce476..c29b7c2a6 100644 --- a/examples/src/legacy/one_kms_cmk_streaming_data.py +++ b/examples/src/legacy/one_kms_cmk_streaming_data.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing basic encryption and decryption of streaming data in memory using one KMS CMK.""" import filecmp diff --git a/examples/src/legacy/one_kms_cmk_unsigned.py b/examples/src/legacy/one_kms_cmk_unsigned.py index 9794202e6..7854fea30 100644 --- a/examples/src/legacy/one_kms_cmk_unsigned.py +++ b/examples/src/legacy/one_kms_cmk_unsigned.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing basic encryption and decryption of a value already in memory using one AWS KMS CMK with an unsigned algorithm. diff --git a/examples/src/legacy/set_commitment.py b/examples/src/legacy/set_commitment.py index 7d58461c9..d989f1a31 100644 --- a/examples/src/legacy/set_commitment.py +++ b/examples/src/legacy/set_commitment.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Example showing how to disable commitment. Note: This configuration should only be used as part of a migration from version 1.x to 2.x, or for advanced users diff --git a/examples/test/legacy/examples_test_utils.py b/examples/test/legacy/examples_test_utils.py index afd531cc6..3f877e301 100644 --- a/examples/test/legacy/examples_test_utils.py +++ b/examples/test/legacy/examples_test_utils.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper utilities for use while testing examples.""" import os import sys diff --git a/examples/test/legacy/test_i_basic_encryption.py b/examples/test/legacy/test_i_basic_encryption.py index a2a96b08f..5ef8c5bbd 100644 --- a/examples/test/legacy/test_i_basic_encryption.py +++ b/examples/test/legacy/test_i_basic_encryption.py @@ -1,15 +1,5 @@ -# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the Strings examples in the AWS-hosted documentation.""" import botocore.session import pytest diff --git a/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py b/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py index af9fb223e..08bc5ba59 100644 --- a/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py +++ b/examples/test/legacy/test_i_basic_file_encryption_with_multiple_providers.py @@ -1,15 +1,5 @@ -# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the Bytes Streams Multiple Providers examples in the AWS-hosted documentation.""" import os import tempfile diff --git a/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py b/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py index d4dd0534c..26ceaeb08 100644 --- a/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py +++ b/examples/test/legacy/test_i_basic_file_encryption_with_raw_key_provider.py @@ -1,15 +1,5 @@ -# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the Bytes Streams examples in the AWS-hosted documentation.""" import os import tempfile diff --git a/examples/test/legacy/test_i_data_key_caching_basic.py b/examples/test/legacy/test_i_data_key_caching_basic.py index 960059597..4ff15156f 100644 --- a/examples/test/legacy/test_i_data_key_caching_basic.py +++ b/examples/test/legacy/test_i_data_key_caching_basic.py @@ -1,15 +1,5 @@ -# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the basic data key caching example in the AWS-hosted documentation.""" import pytest diff --git a/examples/test/legacy/test_i_discovery_kms_provider.py b/examples/test/legacy/test_i_discovery_kms_provider.py index 09c78fe36..4664613dc 100644 --- a/examples/test/legacy/test_i_discovery_kms_provider.py +++ b/examples/test/legacy/test_i_discovery_kms_provider.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK example.""" import botocore.session diff --git a/examples/test/legacy/test_i_mrk_aware_kms_provider.py b/examples/test/legacy/test_i_mrk_aware_kms_provider.py index 81cd5cfd2..6317edca9 100644 --- a/examples/test/legacy/test_i_mrk_aware_kms_provider.py +++ b/examples/test/legacy/test_i_mrk_aware_kms_provider.py @@ -1,15 +1,5 @@ -# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK example.""" import pytest diff --git a/examples/test/legacy/test_i_multiple_kms_cmk.py b/examples/test/legacy/test_i_multiple_kms_cmk.py index f2ecac660..19cb3234c 100644 --- a/examples/test/legacy/test_i_multiple_kms_cmk.py +++ b/examples/test/legacy/test_i_multiple_kms_cmk.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK example.""" import botocore.session diff --git a/examples/test/legacy/test_i_one_kms_cmk.py b/examples/test/legacy/test_i_one_kms_cmk.py index a8d083e67..669ab8c0b 100644 --- a/examples/test/legacy/test_i_one_kms_cmk.py +++ b/examples/test/legacy/test_i_one_kms_cmk.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK example.""" import botocore.session diff --git a/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py b/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py index 6115ed567..d6098aab1 100644 --- a/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py +++ b/examples/test/legacy/test_i_one_kms_cmk_streaming_data.py @@ -1,15 +1,5 @@ -# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption of streaming data using one KMS CMK example.""" import os import tempfile diff --git a/examples/test/legacy/test_i_one_kms_cmk_unsigned.py b/examples/test/legacy/test_i_one_kms_cmk_unsigned.py index cc9acd949..5b219cfeb 100644 --- a/examples/test/legacy/test_i_one_kms_cmk_unsigned.py +++ b/examples/test/legacy/test_i_one_kms_cmk_unsigned.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK with an unsigned algorithm example.""" import botocore.session diff --git a/examples/test/legacy/test_i_set_commitment.py b/examples/test/legacy/test_i_set_commitment.py index 7f86fdcc2..5e3585b0a 100644 --- a/examples/test/legacy/test_i_set_commitment.py +++ b/examples/test/legacy/test_i_set_commitment.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for the encryption and decryption using one KMS CMK example.""" import botocore.session diff --git a/setup.py b/setup.py index 697cb96ce..8ed2fe4e0 100644 --- a/setup.py +++ b/setup.py @@ -54,11 +54,11 @@ def get_requirements(): "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Security", "Topic :: Security :: Cryptography", diff --git a/src/aws_encryption_sdk/__init__.py b/src/aws_encryption_sdk/__init__.py index 66b779fa5..21d3084a1 100644 --- a/src/aws_encryption_sdk/__init__.py +++ b/src/aws_encryption_sdk/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """High level AWS Encryption SDK client functions.""" # Below are imported for ease of use by implementors import warnings diff --git a/src/aws_encryption_sdk/caches/__init__.py b/src/aws_encryption_sdk/caches/__init__.py index 9d2afa485..a7877f381 100644 --- a/src/aws_encryption_sdk/caches/__init__.py +++ b/src/aws_encryption_sdk/caches/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Common functions and structures for use in cryptographic materials caches. .. versionadded:: 1.3.0 diff --git a/src/aws_encryption_sdk/caches/base.py b/src/aws_encryption_sdk/caches/base.py index 1d923ab2b..9166e79d7 100644 --- a/src/aws_encryption_sdk/caches/base.py +++ b/src/aws_encryption_sdk/caches/base.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Base class interface for caches for use with caching crypto material managers.""" import abc diff --git a/src/aws_encryption_sdk/caches/local.py b/src/aws_encryption_sdk/caches/local.py index 90a961aa7..9832447b7 100644 --- a/src/aws_encryption_sdk/caches/local.py +++ b/src/aws_encryption_sdk/caches/local.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Local, in-memory, LRU, cryptographic materials cache for use with caching cryptographic materials providers.""" import logging import weakref diff --git a/src/aws_encryption_sdk/caches/null.py b/src/aws_encryption_sdk/caches/null.py index f26d3dd54..376de92f3 100644 --- a/src/aws_encryption_sdk/caches/null.py +++ b/src/aws_encryption_sdk/caches/null.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Null cache: a cache which does not cache.""" from ..exceptions import CacheKeyError from . import CryptoMaterialsCacheEntry diff --git a/src/aws_encryption_sdk/compatability.py b/src/aws_encryption_sdk/compatability.py index eeac41a46..9900a8893 100644 --- a/src/aws_encryption_sdk/compatability.py +++ b/src/aws_encryption_sdk/compatability.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains logic for checking ESDK and Python Version""" import sys import warnings @@ -23,9 +13,10 @@ def _warn_deprecated_python(): (2, 7): {"date": DEPRECATION_DATE_MAP["2.x"]}, (3, 4): {"date": DEPRECATION_DATE_MAP["2.x"]}, (3, 5): {"date": "2021-11-10"}, + (3, 7): {"date": "2024-03-04"}, } py_version = (sys.version_info.major, sys.version_info.minor) - minimum_version = (3, 6) + minimum_version = (3, 8) if py_version in deprecated_versions: params = deprecated_versions[py_version] diff --git a/src/aws_encryption_sdk/exceptions.py b/src/aws_encryption_sdk/exceptions.py index ed4fea744..f8d6b8cf5 100644 --- a/src/aws_encryption_sdk/exceptions.py +++ b/src/aws_encryption_sdk/exceptions.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains exception classes for AWS Encryption SDK.""" diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index 42cf45d82..84df9c751 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """AWS Encryption SDK native data structures for defining implementation-specific characteristics.""" import struct from enum import Enum diff --git a/src/aws_encryption_sdk/internal/__init__.py b/src/aws_encryption_sdk/internal/__init__.py index 7a78f48ea..e6f21eae2 100644 --- a/src/aws_encryption_sdk/internal/__init__.py +++ b/src/aws_encryption_sdk/internal/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Internal Implementation Details .. warning:: diff --git a/src/aws_encryption_sdk/internal/arn.py b/src/aws_encryption_sdk/internal/arn.py index 4efe6b7d5..eb0edf5f0 100644 --- a/src/aws_encryption_sdk/internal/arn.py +++ b/src/aws_encryption_sdk/internal/arn.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Utility class for processing Amazon Resource Names (ARNs)""" from aws_encryption_sdk.exceptions import MalformedArnError diff --git a/src/aws_encryption_sdk/internal/crypto/__init__.py b/src/aws_encryption_sdk/internal/crypto/__init__.py index 9717f65bd..26d4f6a4e 100644 --- a/src/aws_encryption_sdk/internal/crypto/__init__.py +++ b/src/aws_encryption_sdk/internal/crypto/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Cryptographic modules.""" # Backwards compatible import for use by RawMasterKeyProvider implementations. from .wrapping_keys import WrappingKey # noqa diff --git a/src/aws_encryption_sdk/internal/crypto/authentication.py b/src/aws_encryption_sdk/internal/crypto/authentication.py index d7ff35278..f59903b2a 100644 --- a/src/aws_encryption_sdk/internal/crypto/authentication.py +++ b/src/aws_encryption_sdk/internal/crypto/authentication.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains authentication primitives.""" import base64 import logging diff --git a/src/aws_encryption_sdk/internal/crypto/data_keys.py b/src/aws_encryption_sdk/internal/crypto/data_keys.py index 13a3bc2b7..518b239a1 100644 --- a/src/aws_encryption_sdk/internal/crypto/data_keys.py +++ b/src/aws_encryption_sdk/internal/crypto/data_keys.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains data key helper functions.""" import logging import struct diff --git a/src/aws_encryption_sdk/internal/crypto/elliptic_curve.py b/src/aws_encryption_sdk/internal/crypto/elliptic_curve.py index d2edde317..a7f1d1446 100644 --- a/src/aws_encryption_sdk/internal/crypto/elliptic_curve.py +++ b/src/aws_encryption_sdk/internal/crypto/elliptic_curve.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains elliptic curve functionality.""" import logging from collections import namedtuple diff --git a/src/aws_encryption_sdk/internal/crypto/encryption.py b/src/aws_encryption_sdk/internal/crypto/encryption.py index 1e5523826..4766e22e8 100644 --- a/src/aws_encryption_sdk/internal/crypto/encryption.py +++ b/src/aws_encryption_sdk/internal/crypto/encryption.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains encryption primitives and helper functions.""" import logging diff --git a/src/aws_encryption_sdk/internal/crypto/iv.py b/src/aws_encryption_sdk/internal/crypto/iv.py index e5424057b..e0c7f975e 100644 --- a/src/aws_encryption_sdk/internal/crypto/iv.py +++ b/src/aws_encryption_sdk/internal/crypto/iv.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Helper functions used for generating deterministic initialization vectors (IVs). diff --git a/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py b/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py index da9bc9b6b..903e6c863 100644 --- a/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py +++ b/src/aws_encryption_sdk/internal/crypto/wrapping_keys.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Contains wrapping key primitives.""" import logging import os diff --git a/src/aws_encryption_sdk/internal/defaults.py b/src/aws_encryption_sdk/internal/defaults.py index 184e36bbc..833deec83 100644 --- a/src/aws_encryption_sdk/internal/defaults.py +++ b/src/aws_encryption_sdk/internal/defaults.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Default values for AWS Encryption SDK.""" import io diff --git a/src/aws_encryption_sdk/internal/formatting/__init__.py b/src/aws_encryption_sdk/internal/formatting/__init__.py index 9dd59a29f..8760f7855 100644 --- a/src/aws_encryption_sdk/internal/formatting/__init__.py +++ b/src/aws_encryption_sdk/internal/formatting/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Formatting functions for aws_encryption_sdk.""" from .serialize import serialize_header diff --git a/src/aws_encryption_sdk/internal/formatting/deserialize.py b/src/aws_encryption_sdk/internal/formatting/deserialize.py index 1b46a8b7d..22cb84a30 100644 --- a/src/aws_encryption_sdk/internal/formatting/deserialize.py +++ b/src/aws_encryption_sdk/internal/formatting/deserialize.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Components for handling AWS Encryption SDK message deserialization.""" from __future__ import division diff --git a/src/aws_encryption_sdk/internal/formatting/encryption_context.py b/src/aws_encryption_sdk/internal/formatting/encryption_context.py index 5f8b39327..949ebe6f2 100644 --- a/src/aws_encryption_sdk/internal/formatting/encryption_context.py +++ b/src/aws_encryption_sdk/internal/formatting/encryption_context.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Components for handling serialization and deserialization of encryption context data in AWS Encryption SDK messages. diff --git a/src/aws_encryption_sdk/internal/formatting/serialize.py b/src/aws_encryption_sdk/internal/formatting/serialize.py index 9f1325f98..f2920a1ac 100644 --- a/src/aws_encryption_sdk/internal/formatting/serialize.py +++ b/src/aws_encryption_sdk/internal/formatting/serialize.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Components for handling AWS Encryption SDK message serialization.""" import logging import struct diff --git a/src/aws_encryption_sdk/internal/str_ops.py b/src/aws_encryption_sdk/internal/str_ops.py index 75b70be92..f92769245 100644 --- a/src/aws_encryption_sdk/internal/str_ops.py +++ b/src/aws_encryption_sdk/internal/str_ops.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper functions for consistently obtaining str and bytes objects in both Python2 and Python3.""" import codecs diff --git a/src/aws_encryption_sdk/internal/structures.py b/src/aws_encryption_sdk/internal/structures.py index 2730bd19a..152e021b0 100644 --- a/src/aws_encryption_sdk/internal/structures.py +++ b/src/aws_encryption_sdk/internal/structures.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Public data structures for aws_encryption_sdk.""" import attr import six diff --git a/src/aws_encryption_sdk/internal/utils/__init__.py b/src/aws_encryption_sdk/internal/utils/__init__.py index b08121281..7ce1dcdb2 100644 --- a/src/aws_encryption_sdk/internal/utils/__init__.py +++ b/src/aws_encryption_sdk/internal/utils/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper utility functions for AWS Encryption SDK.""" import io import logging diff --git a/src/aws_encryption_sdk/internal/utils/commitment.py b/src/aws_encryption_sdk/internal/utils/commitment.py index 1af27dcd0..c6d5950d7 100644 --- a/src/aws_encryption_sdk/internal/utils/commitment.py +++ b/src/aws_encryption_sdk/internal/utils/commitment.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper functions for validating commitment policies and algorithms for the AWS Encryption SDK.""" from aws_encryption_sdk.exceptions import ActionNotAllowedError from aws_encryption_sdk.identifiers import CommitmentPolicy diff --git a/src/aws_encryption_sdk/internal/utils/signature.py b/src/aws_encryption_sdk/internal/utils/signature.py index 74b481eb6..7a3558005 100644 --- a/src/aws_encryption_sdk/internal/utils/signature.py +++ b/src/aws_encryption_sdk/internal/utils/signature.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper functions for validating signature policies and algorithms for the AWS Encryption SDK.""" from enum import Enum diff --git a/src/aws_encryption_sdk/internal/utils/streams.py b/src/aws_encryption_sdk/internal/utils/streams.py index 0ab9a9524..5b787c275 100644 --- a/src/aws_encryption_sdk/internal/utils/streams.py +++ b/src/aws_encryption_sdk/internal/utils/streams.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper stream utility objects for AWS Encryption SDK.""" import io diff --git a/src/aws_encryption_sdk/key_providers/__init__.py b/src/aws_encryption_sdk/key_providers/__init__.py index 867d1e0ca..fdf6acfbc 100644 --- a/src/aws_encryption_sdk/key_providers/__init__.py +++ b/src/aws_encryption_sdk/key_providers/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """All provided master key provider and master keys.""" diff --git a/src/aws_encryption_sdk/key_providers/base.py b/src/aws_encryption_sdk/key_providers/base.py index d0871e802..a855ee596 100644 --- a/src/aws_encryption_sdk/key_providers/base.py +++ b/src/aws_encryption_sdk/key_providers/base.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Base class interface for Master Key Providers.""" import abc import logging diff --git a/src/aws_encryption_sdk/key_providers/kms.py b/src/aws_encryption_sdk/key_providers/kms.py index ab18c62ed..45402077d 100644 --- a/src/aws_encryption_sdk/key_providers/kms.py +++ b/src/aws_encryption_sdk/key_providers/kms.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Master Key Providers for use with AWS KMS""" import abc import functools diff --git a/src/aws_encryption_sdk/key_providers/raw.py b/src/aws_encryption_sdk/key_providers/raw.py index 57a1d5edf..f3d8ec478 100644 --- a/src/aws_encryption_sdk/key_providers/raw.py +++ b/src/aws_encryption_sdk/key_providers/raw.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Resources required for Raw Master Keys.""" import abc import logging diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 950dd87cd..706770405 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Primitive structures for use when interacting with crypto material managers. .. versionadded:: 1.3.0 diff --git a/src/aws_encryption_sdk/materials_managers/base.py b/src/aws_encryption_sdk/materials_managers/base.py index e8ffe8a5e..7820d9042 100644 --- a/src/aws_encryption_sdk/materials_managers/base.py +++ b/src/aws_encryption_sdk/materials_managers/base.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Base class interface for crypto material managers.""" import abc diff --git a/src/aws_encryption_sdk/materials_managers/caching.py b/src/aws_encryption_sdk/materials_managers/caching.py index 826c3be79..b1a0ecab5 100644 --- a/src/aws_encryption_sdk/materials_managers/caching.py +++ b/src/aws_encryption_sdk/materials_managers/caching.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Caching crypto material manager.""" import logging import uuid diff --git a/src/aws_encryption_sdk/materials_managers/default.py b/src/aws_encryption_sdk/materials_managers/default.py index e708f25e2..4a7119792 100644 --- a/src/aws_encryption_sdk/materials_managers/default.py +++ b/src/aws_encryption_sdk/materials_managers/default.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Default crypto material manager class.""" import logging diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index a86112610..64d77b91a 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """High level AWS Encryption SDK client for streaming objects.""" from __future__ import division diff --git a/src/aws_encryption_sdk/structures.py b/src/aws_encryption_sdk/structures.py index 52d16dd4c..a09391d5b 100644 --- a/src/aws_encryption_sdk/structures.py +++ b/src/aws_encryption_sdk/structures.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Public data structures for aws_encryption_sdk.""" import attr import six diff --git a/test/__init__.py b/test/__init__.py index 53a960891..f94fd12a2 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,12 +1,2 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/functional/__init__.py b/test/functional/__init__.py index 53a960891..f94fd12a2 100644 --- a/test/functional/__init__.py +++ b/test/functional/__init__.py @@ -1,12 +1,2 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/functional/key_providers/__init__.py b/test/functional/key_providers/__init__.py index cf81c339a..f94fd12a2 100644 --- a/test/functional/key_providers/__init__.py +++ b/test/functional/key_providers/__init__.py @@ -1,12 +1,2 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/functional/key_providers/test_base.py b/test/functional/key_providers/test_base.py index c85f65711..ebec95558 100644 --- a/test/functional/key_providers/test_base.py +++ b/test/functional/key_providers/test_base.py @@ -1,15 +1,5 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Functional tests for ``aws_encryption_sdk.key_providers.base``.""" import itertools diff --git a/test/functional/test_f_aws_encryption_sdk_client.py b/test/functional/test_f_aws_encryption_sdk_client.py index 7310e580f..244f8f7d7 100644 --- a/test/functional/test_f_aws_encryption_sdk_client.py +++ b/test/functional/test_f_aws_encryption_sdk_client.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Functional test suite for aws_encryption_sdk.kms_thick_client""" from __future__ import division diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index 0d4c3249d..fdfe281ae 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Functional test suite for functionality related to key commitment.""" from test.functional.test_f_aws_encryption_sdk_client import fake_kms_key_provider diff --git a/test/functional/test_f_crypto.py b/test/functional/test_f_crypto.py index e0deb04f0..518139603 100644 --- a/test/functional/test_f_crypto.py +++ b/test/functional/test_f_crypto.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Functional test suite for Elliptic Curve static length signature calculation.""" import pytest from cryptography.hazmat.backends import default_backend diff --git a/test/functional/test_f_crypto_iv.py b/test/functional/test_f_crypto_iv.py index 815f025ac..a58c503cc 100644 --- a/test/functional/test_f_crypto_iv.py +++ b/test/functional/test_f_crypto_iv.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for IV generation helper functions.""" import pytest diff --git a/test/functional/test_f_xcompat.py b/test/functional/test_f_xcompat.py index 790724367..8b511ceca 100644 --- a/test/functional/test_f_xcompat.py +++ b/test/functional/test_f_xcompat.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Functional test suite testing decryption of known good test files encrypted using static RawMasterKeyProvider.""" import base64 import json diff --git a/test/integration/__init__.py b/test/integration/__init__.py index 53a960891..f94fd12a2 100644 --- a/test/integration/__init__.py +++ b/test/integration/__init__.py @@ -1,12 +1,2 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/integration/integration_test_utils.py b/test/integration/integration_test_utils.py index 5d40f8124..fbd3774e5 100644 --- a/test/integration/integration_test_utils.py +++ b/test/integration/integration_test_utils.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Utility functions to handle configuration and credentials setup for integration tests.""" import os diff --git a/test/integration/test_i_aws_encrytion_sdk_client.py b/test/integration/test_i_aws_encrytion_sdk_client.py index 5dd13e4c6..51f5aa492 100644 --- a/test/integration/test_i_aws_encrytion_sdk_client.py +++ b/test/integration/test_i_aws_encrytion_sdk_client.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Integration test suite for `aws_encryption_sdk`.""" import io import logging diff --git a/test/integration/test_i_thread_safety.py b/test/integration/test_i_thread_safety.py index 77407b243..3ddb0ecd1 100644 --- a/test/integration/test_i_thread_safety.py +++ b/test/integration/test_i_thread_safety.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Basic sanity check for ``aws_encryption_sdk`` client behavior when threading.""" from __future__ import division diff --git a/test/integration/test_i_xcompat_kms.py b/test/integration/test_i_xcompat_kms.py index 7cfeee111..1caff028c 100644 --- a/test/integration/test_i_xcompat_kms.py +++ b/test/integration/test_i_xcompat_kms.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Integration test suite testing decryption of known good test files encrypted using KMSMasterKeyProvider.""" import json import os diff --git a/test/integration/test_kat_commitment.py b/test/integration/test_kat_commitment.py index e72277787..78891941c 100644 --- a/test/integration/test_kat_commitment.py +++ b/test/integration/test_kat_commitment.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Known answer test suite for functionality related to key commitment.""" import base64 import json diff --git a/test/unit/__init__.py b/test/unit/__init__.py index 53a960891..f94fd12a2 100644 --- a/test/unit/__init__.py +++ b/test/unit/__init__.py @@ -1,12 +1,2 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/unit/test_algorithm_suite.py b/test/unit/test_algorithm_suite.py index 0176a9f8f..9735088c0 100644 --- a/test/unit/test_algorithm_suite.py +++ b/test/unit/test_algorithm_suite.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.identifiers.AlgorithmSuite.""" import pytest diff --git a/test/unit/test_arn.py b/test/unit/test_arn.py index 141be7322..42a3a7f7e 100644 --- a/test/unit/test_arn.py +++ b/test/unit/test_arn.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.arn functions.""" import pytest diff --git a/test/unit/test_caches.py b/test/unit/test_caches.py index 8f7d32280..465325f97 100644 --- a/test/unit/test_caches.py +++ b/test/unit/test_caches.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.caches common functions.""" import struct from base64 import b64decode diff --git a/test/unit/test_caches_base.py b/test/unit/test_caches_base.py index c24b1b04c..f62d81dbb 100644 --- a/test/unit/test_caches_base.py +++ b/test/unit/test_caches_base.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for CryptoMaterialsCache""" import pytest diff --git a/test/unit/test_caches_crypto_cache_entry.py b/test/unit/test_caches_crypto_cache_entry.py index 15c946ee4..cc487427f 100644 --- a/test/unit/test_caches_crypto_cache_entry.py +++ b/test/unit/test_caches_crypto_cache_entry.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for CryptoMaterialsCacheEntry and CryptoMaterialsCacheEntryHints""" import pytest from mock import MagicMock diff --git a/test/unit/test_caches_local.py b/test/unit/test_caches_local.py index 6ced05d8b..e54482ddb 100644 --- a/test/unit/test_caches_local.py +++ b/test/unit/test_caches_local.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit testing suite for LocalCryptoMaterialsCache""" import weakref from collections import OrderedDict, deque diff --git a/test/unit/test_caches_null.py b/test/unit/test_caches_null.py index d593b2332..89fb36864 100644 --- a/test/unit/test_caches_null.py +++ b/test/unit/test_caches_null.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit testing suite for NullCryptoMaterialsCache""" import pytest from mock import MagicMock diff --git a/test/unit/test_commitment.py b/test/unit/test_commitment.py index 4545530e3..18fb4bf08 100644 --- a/test/unit/test_commitment.py +++ b/test/unit/test_commitment.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit testing suite for commitment utility functions""" import pytest from mock import MagicMock diff --git a/test/unit/test_compatability.py b/test/unit/test_compatability.py index bf444052d..bd602c7cd 100644 --- a/test/unit/test_compatability.py +++ b/test/unit/test_compatability.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.compatability""" import sys diff --git a/test/unit/test_crypto.py b/test/unit/test_crypto.py index 23a5c4975..6b0389d11 100644 --- a/test/unit/test_crypto.py +++ b/test/unit/test_crypto.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.crypto""" from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec diff --git a/test/unit/test_crypto_authentication_signer.py b/test/unit/test_crypto_authentication_signer.py index 425f672ed..4d2623c62 100644 --- a/test/unit/test_crypto_authentication_signer.py +++ b/test/unit/test_crypto_authentication_signer.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.authentication.Signer``.""" import cryptography.hazmat.primitives.serialization import pytest diff --git a/test/unit/test_crypto_authentication_verifier.py b/test/unit/test_crypto_authentication_verifier.py index 05af581eb..7562fa762 100644 --- a/test/unit/test_crypto_authentication_verifier.py +++ b/test/unit/test_crypto_authentication_verifier.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.authentication.Verifier``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_crypto_data_keys.py b/test/unit/test_crypto_data_keys.py index 6d00f5e8c..5dd2366db 100644 --- a/test/unit/test_crypto_data_keys.py +++ b/test/unit/test_crypto_data_keys.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.data_keys``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_crypto_elliptic_curve.py b/test/unit/test_crypto_elliptic_curve.py index 02497b31c..1e04d6e3c 100644 --- a/test/unit/test_crypto_elliptic_curve.py +++ b/test/unit/test_crypto_elliptic_curve.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.elliptic_curve``.""" import sys diff --git a/test/unit/test_crypto_encryption_decryptor.py b/test/unit/test_crypto_encryption_decryptor.py index f709bea1e..57ea90383 100644 --- a/test/unit/test_crypto_encryption_decryptor.py +++ b/test/unit/test_crypto_encryption_decryptor.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.encryption.Decryptor``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_crypto_encryption_encryptor.py b/test/unit/test_crypto_encryption_encryptor.py index 207aa36dd..717f95e7c 100644 --- a/test/unit/test_crypto_encryption_encryptor.py +++ b/test/unit/test_crypto_encryption_encryptor.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.encryption.Encryptor``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_crypto_prehashing_authenticator.py b/test/unit/test_crypto_prehashing_authenticator.py index 104133da0..631391f53 100644 --- a/test/unit/test_crypto_prehashing_authenticator.py +++ b/test/unit/test_crypto_prehashing_authenticator.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto._PrehashingAuthenticater``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_crypto_wrapping_keys.py b/test/unit/test_crypto_wrapping_keys.py index 459d2cc40..1971b2934 100644 --- a/test/unit/test_crypto_wrapping_keys.py +++ b/test/unit/test_crypto_wrapping_keys.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for ``aws_encryption_sdk.internal.crypto.wrapping_keys``.""" import pytest from mock import MagicMock, sentinel diff --git a/test/unit/test_defaults.py b/test/unit/test_defaults.py index 37965768b..cf1157f1e 100644 --- a/test/unit/test_defaults.py +++ b/test/unit/test_defaults.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite to verify calculated values in aws_encryption_sdk.internal.defaults""" import pytest diff --git a/test/unit/test_deserialize.py b/test/unit/test_deserialize.py index f5d257971..fc77634c2 100644 --- a/test/unit/test_deserialize.py +++ b/test/unit/test_deserialize.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.deserialize""" import io import struct diff --git a/test/unit/test_encryption_client.py b/test/unit/test_encryption_client.py index db2ca1c4c..06cfe16e8 100644 --- a/test/unit/test_encryption_client.py +++ b/test/unit/test_encryption_client.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.EncryptionSDKClient""" import warnings diff --git a/test/unit/test_encryption_context.py b/test/unit/test_encryption_context.py index ccc18c219..bd717fbd8 100644 --- a/test/unit/test_encryption_context.py +++ b/test/unit/test_encryption_context.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.formatting.encryption_context""" import pytest diff --git a/test/unit/test_identifiers.py b/test/unit/test_identifiers.py index 3fd421b65..f475fe329 100644 --- a/test/unit/test_identifiers.py +++ b/test/unit/test_identifiers.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.identifiers""" import pytest from mock import Mock diff --git a/test/unit/test_internal_structures.py b/test/unit/test_internal_structures.py index d57166982..29b780b3a 100644 --- a/test/unit/test_internal_structures.py +++ b/test/unit/test_internal_structures.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.structures""" import pytest diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index 2d892bd36..4de2030a4 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.materials_managers""" import pytest from mock import MagicMock diff --git a/test/unit/test_material_managers_base.py b/test/unit/test_material_managers_base.py index 34501e59a..8d55a290b 100644 --- a/test/unit/test_material_managers_base.py +++ b/test/unit/test_material_managers_base.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.materials_managers.base""" import pytest diff --git a/test/unit/test_material_managers_caching.py b/test/unit/test_material_managers_caching.py index 04540e7bd..7f186becc 100644 --- a/test/unit/test_material_managers_caching.py +++ b/test/unit/test_material_managers_caching.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for CachingCryptoMaterialsManager""" import pytest diff --git a/test/unit/test_material_managers_default.py b/test/unit/test_material_managers_default.py index 4d35d072b..bd872ddfd 100644 --- a/test/unit/test_material_managers_default.py +++ b/test/unit/test_material_managers_default.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.materials_managers.default""" import pytest diff --git a/test/unit/test_providers_base_master_key.py b/test/unit/test_providers_base_master_key.py index 86c290196..6514e87c2 100644 --- a/test/unit/test_providers_base_master_key.py +++ b/test/unit/test_providers_base_master_key.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.key_providers.base.MasterKey""" import attr import pytest diff --git a/test/unit/test_providers_base_master_key_config.py b/test/unit/test_providers_base_master_key_config.py index 8b6c8731a..994fff637 100644 --- a/test/unit/test_providers_base_master_key_config.py +++ b/test/unit/test_providers_base_master_key_config.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.key_providers.base.MasterKeyConfig""" import pytest diff --git a/test/unit/test_providers_base_master_key_provider.py b/test/unit/test_providers_base_master_key_provider.py index a4b4e3832..fc18769a6 100644 --- a/test/unit/test_providers_base_master_key_provider.py +++ b/test/unit/test_providers_base_master_key_provider.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.key_providers.base.MasterKeyProvider""" import attr import pytest diff --git a/test/unit/test_providers_base_master_key_provider_config.py b/test/unit/test_providers_base_master_key_provider_config.py index 0e21ded80..56ea6fe45 100644 --- a/test/unit/test_providers_base_master_key_provider_config.py +++ b/test/unit/test_providers_base_master_key_provider_config.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.key_providers.base.MasterKeyProviderConfig""" from aws_encryption_sdk.key_providers.base import MasterKeyProviderConfig # noqa pylint: disable=unused-import diff --git a/test/unit/test_providers_kms_master_key.py b/test/unit/test_providers_kms_master_key.py index be91c96c7..01a87d4fd 100644 --- a/test/unit/test_providers_kms_master_key.py +++ b/test/unit/test_providers_kms_master_key.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.key_providers.kms.KMSMasterKey""" import botocore.client import pytest diff --git a/test/unit/test_providers_kms_master_key_config.py b/test/unit/test_providers_kms_master_key_config.py index 1501c951f..baaf0573d 100644 --- a/test/unit/test_providers_kms_master_key_config.py +++ b/test/unit/test_providers_kms_master_key_config.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.key_providers.kms.KMSMasterKeyConfig""" import boto3 import pytest diff --git a/test/unit/test_providers_kms_master_key_provider.py b/test/unit/test_providers_kms_master_key_provider.py index 6e142bb58..6cc6c81e4 100644 --- a/test/unit/test_providers_kms_master_key_provider.py +++ b/test/unit/test_providers_kms_master_key_provider.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite from aws_encryption_sdk.key_providers.kms.KMSMasterKeyProvider""" import botocore.client import botocore.session diff --git a/test/unit/test_providers_kms_master_key_provider_config.py b/test/unit/test_providers_kms_master_key_provider_config.py index affa74102..bc7092c5f 100644 --- a/test/unit/test_providers_kms_master_key_provider_config.py +++ b/test/unit/test_providers_kms_master_key_provider_config.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.key_providers.kms.KMSMasterKeyProviderConfig""" import botocore.session import pytest diff --git a/test/unit/test_providers_raw_master_key.py b/test/unit/test_providers_raw_master_key.py index 9abcd14c6..93f40ff22 100644 --- a/test/unit/test_providers_raw_master_key.py +++ b/test/unit/test_providers_raw_master_key.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.key_providers.raw.RawMasterKey""" import pytest from mock import MagicMock, patch, sentinel diff --git a/test/unit/test_providers_raw_master_key_config.py b/test/unit/test_providers_raw_master_key_config.py index d06feae87..e61e7bf1e 100644 --- a/test/unit/test_providers_raw_master_key_config.py +++ b/test/unit/test_providers_raw_master_key_config.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.key_providers.raw.RawMasterKeyConfig""" import pytest import six diff --git a/test/unit/test_providers_raw_master_key_provider.py b/test/unit/test_providers_raw_master_key_provider.py index 5128b1e22..aeb23887c 100644 --- a/test/unit/test_providers_raw_master_key_provider.py +++ b/test/unit/test_providers_raw_master_key_provider.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.key_providers.raw.RawMasterKeyProvider""" import attr import pytest diff --git a/test/unit/test_serialize.py b/test/unit/test_serialize.py index 06ac6126b..4bcd703d8 100644 --- a/test/unit/test_serialize.py +++ b/test/unit/test_serialize.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.formatting.serialize""" import pytest from mock import MagicMock, patch, sentinel diff --git a/test/unit/test_streaming_client_configs.py b/test/unit/test_streaming_client_configs.py index 435aff0da..fc066ef1a 100644 --- a/test/unit/test_streaming_client_configs.py +++ b/test/unit/test_streaming_client_configs.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite to validate aws_encryption_sdk.streaming_client config classes.""" import io diff --git a/test/unit/test_streaming_client_encryption_stream.py b/test/unit/test_streaming_client_encryption_stream.py index c54455654..30497d0c8 100644 --- a/test/unit/test_streaming_client_encryption_stream.py +++ b/test/unit/test_streaming_client_encryption_stream.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.streaming_client._EncryptionStream""" import copy import io diff --git a/test/unit/test_streaming_client_stream_decryptor.py b/test/unit/test_streaming_client_stream_decryptor.py index ce3d6ee3c..adcb7215b 100644 --- a/test/unit/test_streaming_client_stream_decryptor.py +++ b/test/unit/test_streaming_client_stream_decryptor.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.streaming_client.StreamDecryptor""" # noqa pylint: disable=too-many-lines import io diff --git a/test/unit/test_streaming_client_stream_encryptor.py b/test/unit/test_streaming_client_stream_encryptor.py index 4df79e146..283f60fb0 100644 --- a/test/unit/test_streaming_client_stream_encryptor.py +++ b/test/unit/test_streaming_client_stream_encryptor.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.streaming_client.StreamEncryptor""" # noqa pylint: disable=too-many-lines import io diff --git a/test/unit/test_structures.py b/test/unit/test_structures.py index 416777505..28db3eaf2 100644 --- a/test/unit/test_structures.py +++ b/test/unit/test_structures.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.structures""" import pytest diff --git a/test/unit/test_util_str_ops.py b/test/unit/test_util_str_ops.py index 5a6ef2546..b43fcda4b 100644 --- a/test/unit/test_util_str_ops.py +++ b/test/unit/test_util_str_ops.py @@ -1,16 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.internal.str_ops""" import codecs diff --git a/test/unit/test_util_streams.py b/test/unit/test_util_streams.py index ab7b05152..147f60c65 100644 --- a/test/unit/test_util_streams.py +++ b/test/unit/test_util_streams.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Unit test suite for aws_encryption_sdk.internal.utils.streams""" import io diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 69f9f060d..82ee317f1 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -1,16 +1,6 @@ # coding: utf-8 -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test suite for aws_encryption_sdk.internal.utils""" import io diff --git a/test/unit/test_values.py b/test/unit/test_values.py index cb48c8c74..9ae2df354 100644 --- a/test/unit/test_values.py +++ b/test/unit/test_values.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Values to use in various unit test suites.""" import copy import struct diff --git a/test/unit/unit_test_utils.py b/test/unit/unit_test_utils.py index e43240c8a..ecff483ef 100644 --- a/test/unit/unit_test_utils.py +++ b/test/unit/unit_test_utils.py @@ -1,15 +1,5 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Utility functions to handle common test framework functions.""" import copy import io diff --git a/test_vector_handlers/README.rst b/test_vector_handlers/README.rst index 846400127..9bf6e5ce5 100644 --- a/test_vector_handlers/README.rst +++ b/test_vector_handlers/README.rst @@ -12,7 +12,7 @@ Getting Started Required Prerequisites ====================== -* Python 3.7+ +* Python 3.8+ * aws-encryption-sdk Use diff --git a/test_vector_handlers/setup.py b/test_vector_handlers/setup.py index 54d857db0..f09126929 100644 --- a/test_vector_handlers/setup.py +++ b/test_vector_handlers/setup.py @@ -46,7 +46,6 @@ def get_requirements(): "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", diff --git a/test_vector_handlers/src/awses_test_vectors/__init__.py b/test_vector_handlers/src/awses_test_vectors/__init__.py index 5870f4318..0a9c2d8c7 100644 --- a/test_vector_handlers/src/awses_test_vectors/__init__.py +++ b/test_vector_handlers/src/awses_test_vectors/__init__.py @@ -1,14 +1,4 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Static test vector handling logic for the AWS Encyrption SDK.""" __version__ = "2.0.0" diff --git a/test_vector_handlers/src/awses_test_vectors/commands/__init__.py b/test_vector_handlers/src/awses_test_vectors/commands/__init__.py index 17b493032..52ecb14a1 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/__init__.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """CLI commands.""" diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py index 2a44cd597..d1e7a6811 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Command to test AWS Encryption SDK full message decryption vectors.""" import argparse diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py index 69fe44d78..49f2647fa 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Command to generate AWS Encryption SDK full message decryption vectors.""" import argparse diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py index 268d7ca99..ba7579e6f 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Command to test AWS Encryption SDK full message encryption vectors.""" import argparse diff --git a/test_vector_handlers/src/awses_test_vectors/internal/__init__.py b/test_vector_handlers/src/awses_test_vectors/internal/__init__.py index 34bfd8a1d..9bad12089 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/__init__.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/__init__.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Internal implementation details. .. warning:: diff --git a/test_vector_handlers/src/awses_test_vectors/internal/aws_kms.py b/test_vector_handlers/src/awses_test_vectors/internal/aws_kms.py index 14c109e7d..16425d719 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/aws_kms.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/aws_kms.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Helper utilities for interacting with AWS KMS.""" try: from aws_encryption_sdk.identifiers import AlgorithmSuite diff --git a/test_vector_handlers/src/awses_test_vectors/internal/defaults.py b/test_vector_handlers/src/awses_test_vectors/internal/defaults.py index d72a9287d..fcc8a655a 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/defaults.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/defaults.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Default values for use in AWS Encryption SDK test vector handlers.""" ENCODING = "utf-8" diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mypy_types.py b/test_vector_handlers/src/awses_test_vectors/internal/mypy_types.py index 3712643e8..482b303a0 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/mypy_types.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/mypy_types.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """MyPy types for use in AWS Encryption SDK test vector handlers.""" # mypy types confuse pylint: disable=invalid-name diff --git a/test_vector_handlers/src/awses_test_vectors/internal/util.py b/test_vector_handlers/src/awses_test_vectors/internal/util.py index da5552f13..002e36689 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/util.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/util.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Utility functions for use in AWS Encryption SDK test vector handlers.""" import os import struct diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/__init__.py b/test_vector_handlers/src/awses_test_vectors/manifests/__init__.py index e2472c3bb..c8ba0a088 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/__init__.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Test vector manifest handlers.""" diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/__init__.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/__init__.py index 090bd995e..0a47b9fcc 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/__init__.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/__init__.py @@ -1,13 +1,3 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """Full-message test vector manifest handlers.""" diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index 2aaaf1bca..8c500caba 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ AWS Encryption SDK Decrypt Message manifest handler. diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py index 50c14a091..93510d891 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ AWS Encryption SDK Decrypt Message Generation manifest handler. diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py index 57de8504c..82c1740de 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ AWS Encryption SDK Encrypt Message manifest handler. diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/keys.py b/test_vector_handlers/src/awses_test_vectors/manifests/keys.py index cba6b7e25..7c55a1617 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/keys.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/keys.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Keys Manifest handler. diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index a1a7ae4af..49b517eae 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ AWS Encryption SDK master key specification utilities. diff --git a/test_vector_handlers/test/aws-crypto-tools-test-vector-framework b/test_vector_handlers/test/aws-crypto-tools-test-vector-framework index 9eb2fcbbe..fc793e257 160000 --- a/test_vector_handlers/test/aws-crypto-tools-test-vector-framework +++ b/test_vector_handlers/test/aws-crypto-tools-test-vector-framework @@ -1 +1 @@ -Subproject commit 9eb2fcbbe47ab30c29d6ad9a8125b1064e0db42a +Subproject commit fc793e257f4a58ae49b92f95a519ba2c31ccff12 diff --git a/test_vector_handlers/test/integration/commands/test_i_full_message_encrypt.py b/test_vector_handlers/test/integration/commands/test_i_full_message_encrypt.py index 6305a15da..58c0de4a4 100644 --- a/test_vector_handlers/test/integration/commands/test_i_full_message_encrypt.py +++ b/test_vector_handlers/test/integration/commands/test_i_full_message_encrypt.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Integration tests for ``awses_test_vectors.commands``. """ diff --git a/test_vector_handlers/test/integration/integration_test_utils.py b/test_vector_handlers/test/integration/integration_test_utils.py index fbe6cf7b7..ef8d0fb88 100644 --- a/test_vector_handlers/test/integration/integration_test_utils.py +++ b/test_vector_handlers/test/integration/integration_test_utils.py @@ -1,15 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 """ Integration test utilities. """ diff --git a/tox.ini b/tox.ini index 8d4af1d2d..9152f51a6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = # <3.11: run all non-MPL tests - py{37,38,39,310}-{local,integ,accept,examples}, + py{38,39,310}-{local,integ,accept,examples}, # >=3.11: run all tests with MPL installed and without MPL installed # The `-mpl` suffix tells tox to install the MPL. # In the case where the suffix IS NOT appended, From ebbc26b1fb83d7e0bcba66c70012730350b6c60d Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:37:00 -0700 Subject: [PATCH 13/51] chore: performance tests for ESDK-python (#680) --- .gitignore | 6 + buildspec.yml | 8 + codebuild/py311/performance_tests_mpl.yml | 38 +++ codebuild/py312/performance_tests_mpl.yml | 38 +++ performance_tests/README.rst | 219 ++++++++++++++++++ performance_tests/__init__.py | 3 + performance_tests/consolidate_results.py | 49 ++++ performance_tests/pylintrc | 45 ++++ performance_tests/requirements.txt | 5 + performance_tests/requirements_mpl.txt | 1 + performance_tests/results/.gitkeep | 0 performance_tests/setup.cfg | 41 ++++ performance_tests/setup.py | 34 +++ .../__init__.py | 4 + .../keyrings/__init__.py | 3 + .../keyrings/aws_kms_keyring.py | 131 +++++++++++ .../keyrings/raw_aes_keyring.py | 85 +++++++ .../keyrings/raw_rsa_keyring.py | 79 +++++++ .../master_key_providers/__init__.py | 3 + .../aws_kms_master_key_provider.py | 69 ++++++ .../raw_aes_master_key_provider.py | 101 ++++++++ .../raw_rsa_master_key_provider.py | 101 ++++++++ .../utils/__init__.py | 3 + .../utils/util.py | 116 ++++++++++ performance_tests/test/keyrings/__init__.py | 3 + .../test/keyrings/test_aws_kms_keyring.py | 206 ++++++++++++++++ .../test/keyrings/test_raw_aes_keyring.py | 156 +++++++++++++ .../test/keyrings/test_raw_rsa_keyring.py | 163 +++++++++++++ .../test/master_key_providers/__init__.py | 3 + .../test_aws_kms_master_key_provider.py | 165 +++++++++++++ .../test_raw_aes_master_key_provider.py | 156 +++++++++++++ .../test_raw_rsa_master_key_provider.py | 156 +++++++++++++ performance_tests/test/resources/__init__.py | 3 + .../ciphertext/kms/ciphertext-data-empty.ct | Bin 0 -> 587 bytes .../ciphertext/kms/ciphertext-data-large.ct | Bin 0 -> 8619 bytes .../ciphertext/kms/ciphertext-data-medium.ct | Bin 0 -> 4587 bytes .../ciphertext/kms/ciphertext-data-small.ct | Bin 0 -> 623 bytes .../raw_aes/ciphertext-data-empty.ct | Bin 0 -> 454 bytes .../raw_aes/ciphertext-data-large.ct | Bin 0 -> 8486 bytes .../raw_aes/ciphertext-data-medium.ct | Bin 0 -> 4454 bytes .../raw_aes/ciphertext-data-small.ct | Bin 0 -> 490 bytes .../raw_rsa/ciphertext-data-empty.ct | Bin 0 -> 899 bytes .../raw_rsa/ciphertext-data-large.ct | Bin 0 -> 8931 bytes .../raw_rsa/ciphertext-data-medium.ct | Bin 0 -> 4899 bytes .../raw_rsa/ciphertext-data-small.ct | Bin 0 -> 935 bytes .../plaintext/plaintext-data-empty.dat | 0 .../plaintext/plaintext-data-large.dat | 21 ++ .../plaintext/plaintext-data-medium.dat | 11 + .../plaintext/plaintext-data-small.dat | 1 + performance_tests/tox.ini | 215 +++++++++++++++++ 50 files changed, 2441 insertions(+) create mode 100644 codebuild/py311/performance_tests_mpl.yml create mode 100644 codebuild/py312/performance_tests_mpl.yml create mode 100644 performance_tests/README.rst create mode 100644 performance_tests/__init__.py create mode 100644 performance_tests/consolidate_results.py create mode 100644 performance_tests/pylintrc create mode 100644 performance_tests/requirements.txt create mode 100644 performance_tests/requirements_mpl.txt create mode 100644 performance_tests/results/.gitkeep create mode 100644 performance_tests/setup.cfg create mode 100644 performance_tests/setup.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py create mode 100644 performance_tests/test/keyrings/__init__.py create mode 100644 performance_tests/test/keyrings/test_aws_kms_keyring.py create mode 100644 performance_tests/test/keyrings/test_raw_aes_keyring.py create mode 100644 performance_tests/test/keyrings/test_raw_rsa_keyring.py create mode 100644 performance_tests/test/master_key_providers/__init__.py create mode 100644 performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py create mode 100644 performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py create mode 100644 performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py create mode 100644 performance_tests/test/resources/__init__.py create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-empty.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-large.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-medium.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-small.dat create mode 100644 performance_tests/tox.ini diff --git a/.gitignore b/.gitignore index 24df397ed..2843404d0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,12 @@ __pycache__ .pytest_cache # Ignore key materials generated by examples or tests test_keyrings/ +# Ignore results of performance test +performance_tests/results/*.csv +performance_tests/results/*.pstats +performance_tests/results/*.png +# Ignore the memory profile logs +mprofile_* # PyCharm .idea/ diff --git a/buildspec.yml b/buildspec.yml index 086743dbc..583fae56f 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -126,6 +126,10 @@ batch: buildspec: codebuild/py311/integ_mpl.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_performance_tests_mpl + buildspec: codebuild/py311/performance_tests_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py311_examples buildspec: codebuild/py311/examples.yml env: @@ -212,6 +216,10 @@ batch: buildspec: codebuild/py312/integ_mpl.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_performance_tests_mpl + buildspec: codebuild/py312/performance_tests_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_examples buildspec: codebuild/py312/examples.yml env: diff --git a/codebuild/py311/performance_tests_mpl.yml b/codebuild/py311/performance_tests_mpl.yml new file mode 100644 index 000000000..2debb1185 --- /dev/null +++ b/codebuild/py311/performance_tests_mpl.yml @@ -0,0 +1,38 @@ +# Runs the performance tests for the MPL in an environment with the MPL installed +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.11.0 + - pyenv local 3.11.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - cd performance_tests/ + - tox -e py311-performance_tests-mpl diff --git a/codebuild/py312/performance_tests_mpl.yml b/codebuild/py312/performance_tests_mpl.yml new file mode 100644 index 000000000..97dbf359f --- /dev/null +++ b/codebuild/py312/performance_tests_mpl.yml @@ -0,0 +1,38 @@ +# Runs the performance tests for the MPL in an environment with the MPL installed +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.12.0 + - pyenv local 3.12.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - cd performance_tests/ + - tox -e py312-performance_tests-mpl diff --git a/performance_tests/README.rst b/performance_tests/README.rst new file mode 100644 index 000000000..ba9b89f15 --- /dev/null +++ b/performance_tests/README.rst @@ -0,0 +1,219 @@ +##################################### +aws-encryption-sdk performance tests +##################################### + +This module runs performance tests for the `AWS Encryption SDK Python`_. + +******** +Overview +******** + +This module tests the following keyrings / master key providers: + +1. KMS Keyring / KMS Master Key Provider +2. Raw AES Keyring / AES Master Key Provider +3. Raw RSA Keyring / RSA Master Key Provider +4. Hierarchy Keyring +5. Caching CMM + +For each test on the above keyrings / master key providers, this package measures: + +1. Execution time +2. Total memory consumption + +For each keyring / master key provider, the execution time and memory consumption +is measured for three operations: + +1. Create keyring / master key provider +2. Encrypt +3. Decrypt + +The usage of the performance tests is demonstrated through an `AWS KMS Keyring`_. +However, the procedure is the same for any keyring / master key provider, with slight +changes in the input arguments. + +The results for the performance test will be available in the results folder in the +performance_tests directory. + +********************** +Required Prerequisites +********************** + +* Python 3.8+ +* aws-encryption-sdk +* boto3 >= 1.10.0 +* click +* tqdm +* pytest + +Recommended Prerequisites +========================= + +* aws-cryptographic-material-providers: >= 1.0.0 + * Requires Python 3.11+. + +***** +Usage +***** + +Execution Time +============== + +Create Keyring +-------------- +To run the performance test for execution time, please use the +following commands in the performance_tests directory. + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py create + + Create a keyring to use for encryption and decryption. + + optional arguments: + -h, --help show this help message and exit. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Encrypt +------- + +To run the performance test for execution time, please use the following +commands in the performance_tests directory: + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py encrypt + + optional arguments: + -h, --help show this help message and exit. + --plaintext_data_filename PLAINTEXT_DATA_FILENAME Filename containing plaintext data + you want to encrypt. + default='test/resources/plaintext/plaintext-data-medium.dat'. + You can choose to use any other plaintext + file as well. Some example plaintext + data files are present in the + 'test/resources' directory. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Decrypt +------- + +To run the performance test for execution time, please use the +following commands in the performance_tests directory + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py decrypt + + optional arguments: + -h, --help show this help message and exit. + --ciphertext_data_filename CIPHERTEXT_DATA_FILENAME Filename containing ciphertext data + you want to decrypt. + default='test/resources/ciphertext/kms/ciphertext-data-medium.ct'. + You can choose to use any other + ciphertext file as well. Some example + ciphertext data files are present in + the 'test/resources' directory. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Consolidate Time Results +======================== + +In order to find the minimum, maximum, average, 99th percentile and bottom +99th percentile trimmed average times from the n_iters runs, please use the +following script from the performance_tests directory with the csv file +containing times for each of the n_iters runs generated in the previous +"Execution Time" section: + +.. code:: + + usage: python consolidate_results.py results/kms_keyring_decrypt.csv + +Memory Consumption +================== + +To get the memory consumption, simply replace 'python' +with 'mprof run' in the previously mentioned commands. + +For example, if you want to calculate the memory consumption +of the encrypt function of a AWS KMS Keyring, simply write: + +.. code:: + + usage: mprof run test/keyrings/test_aws_kms_keyring.py encrypt + + +This should generate an mprofile log file in your current directory. +This mprofile log file contains the total memory consumed by the program +with respect to time elapsed. +To plot the memory consumption with respect to time, please use the following +command from the same directory + +.. code:: + + usage: mprof plot + + +This 'mprof plot' command will plot the most recent mprofile log file. + + +Performance Graph +================= + +To generate a performance graph, please use the following command +to generate the pstats log file by specifying the output pstats file +path. Here, 'results/kms_keyring_create.pstats' is set as the default +output file. + +.. code:: + + usage: python -m cProfile -o results/kms_keyring_create.pstats test/keyrings/test_aws_kms_keyring.py create + + +After generating the pstats file, please run the following command +to generate the performance graph. The output performance graph will +be a .png file that you specify. Here, 'results/kms_keyring_create.png' +is set as the default output file. + +.. code:: + + usage: gprof2dot -f pstats results/kms_keyring_create.pstats | dot -Tpng -o results/kms_keyring_create.png && eog results/kms_keyring_create.png + + +Note: This project does not adhere to semantic versioning; as such it +makes no guarantees that functionality will persist across major, +minor, or patch versions. +**DO NOT** take a standalone dependency on this library. + +.. _AWS Encryption SDK Python: https://github.com/aws/aws-encryption-sdk-python/ +.. _AWS KMS Keyring: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html diff --git a/performance_tests/__init__.py b/performance_tests/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/consolidate_results.py b/performance_tests/consolidate_results.py new file mode 100644 index 000000000..2601417cc --- /dev/null +++ b/performance_tests/consolidate_results.py @@ -0,0 +1,49 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Script for consolidating results for execution times""" + +import argparse +import csv + +import numpy as np + + +def calculate_statistics(_csv_file): + """Calculate average, trimmed average, minimum, maximum and p99 statistics for execution times in a CSV file.""" + with open(_csv_file, 'r', encoding='utf-8') as file: + reader = csv.reader(file) + data = [float(row[0]) for row in reader] + + output_stats = {} + + # Calculate statistics + if data: + data = np.sort(data) + output_stats['total_entries'] = len(data) + output_stats['average'] = np.mean(data) + output_stats['trimmed_average_99_bottom'] = np.mean(data[0:int(0.99 * len(data))]) + output_stats['minimum'] = min(data) + output_stats['maximum'] = max(data) + output_stats['perc_99'] = np.percentile(data, 99) + return output_stats + + return None + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('csv_file', + help='csv file containing the outputs of execution times for n_iter iterations') + args = parser.parse_args() + + statistics = calculate_statistics(args.csv_file) + if statistics: + print("CSV File:", args.csv_file) + print("Total Entries:", statistics['total_entries']) + print("Average:", statistics['average']) + print("Bottom 99th percentile trimmed average:", statistics['trimmed_average_99_bottom']) + print("Minimum:", statistics['minimum']) + print("Maximum:", statistics['maximum']) + print("99th percentile:", statistics['perc_99']) + else: + print("No data found in the CSV file.") diff --git a/performance_tests/pylintrc b/performance_tests/pylintrc new file mode 100644 index 000000000..8ed5cb105 --- /dev/null +++ b/performance_tests/pylintrc @@ -0,0 +1,45 @@ +[MESSAGE CONTROL] +# Disabling messages that either we don't care about we intentionally break. +disable = + import-error, # ignore mpl import errors + invalid-name, # we prefer long, descriptive, names for examples + bad-continuation, # we let black handle this + ungrouped-imports, # we let isort handle this + no-member, # breaks with attrs + no-self-use, # interesting to keep in mind for later refactoring, but not blocking + useless-object-inheritance, # we need to support Python 2, so no, not useless + duplicate-code, # some examples may be similar + too-few-public-methods, # does not allow value stores + too-many-locals, # examples may sometimes have more locals defined for clarity than would be appropriate in code + no-else-return, # we omit this on purpose for brevity where it would add no value + attribute-defined-outside-init, # breaks with attrs_post_init + abstract-method, # throws false positives on io.BaseIO grandchildren + redefined-outer-name, # we do this on purpose in multiple places + consider-using-f-string # disable until 2022-05-05; 6 months after 3.5 deprecation + +[BASIC] +# Allow function names up to 50 characters +function-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow method names up to 50 characters +method-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow class attribute names up to 50 characters +# Whitelist class attribute names: iv +class-attribute-rgx = (([A-Za-z_][A-Za-z0-9_]{2,50}|(__.*__))$)|(^iv$) +# Whitelist attribute names: iv +attr-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$) +# Whitelist argument names: iv, b +argument-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$) +# Whitelist variable names: iv, b, _b, x, y, r, s +variable-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$)|(^_b$)|(^x$)|(^y$)|(^r$)|(^s$) + +[VARIABLES] +additional-builtins = raw_input + +[DESIGN] +max-args = 10 + +[FORMAT] +max-line-length = 120 + +[REPORTS] +msg-template = {path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/performance_tests/requirements.txt b/performance_tests/requirements.txt new file mode 100644 index 000000000..0b879647f --- /dev/null +++ b/performance_tests/requirements.txt @@ -0,0 +1,5 @@ +attrs >= 17.4.0 +aws-encryption-sdk>=2.3.0 +pytest>=3.3.1 +tqdm +click diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt new file mode 100644 index 000000000..209e10f2c --- /dev/null +++ b/performance_tests/requirements_mpl.txt @@ -0,0 +1 @@ +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/performance_tests/results/.gitkeep b/performance_tests/results/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/performance_tests/setup.cfg b/performance_tests/setup.cfg new file mode 100644 index 000000000..c584a25bd --- /dev/null +++ b/performance_tests/setup.cfg @@ -0,0 +1,41 @@ +[wheel] +universal = 1 + +[metadata] +license_file = LICENSE + +[coverage:run] +branch = True + +[coverage:report] +show_missing = True + +[mypy] +ignore_missing_imports = True + +[flake8] +max_complexity = 10 +max_line_length = 120 +import_order_style = google +application_import_names = aws_encryption_sdk_cli +builtins = raw_input +ignore = + # Ignoring D205 and D400 because of false positives + D205, D400, + # E203 is not PEP8 compliant https://github.com/ambv/black#slices + E203, + # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators + W503 + +[doc8] +max-line-length = 120 + +[isort] +line_length = 120 +# https://github.com/timothycrosley/isort#multi-line-output-modes +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +combine_as_imports = True +not_skip = __init__.py +known_third_party = attr,aws_encryption_sdk,pytest,setuptools,six diff --git a/performance_tests/setup.py b/performance_tests/setup.py new file mode 100644 index 000000000..702813509 --- /dev/null +++ b/performance_tests/setup.py @@ -0,0 +1,34 @@ +"""Performance test for the AWS Encryption SDK for Python.""" +import os +import re + +from setuptools import find_packages, setup + +VERSION_RE = re.compile(r"""__version__ = ['"]([0-9.]+)['"]""") +HERE = os.path.abspath(os.path.dirname(__file__)) + + +def read(*args): + """Read complete file contents.""" + return open(os.path.join(HERE, *args), encoding="utf-8").read() # pylint: disable=consider-using-with + + +def get_version(): + """Read the version from this module.""" + init = read("src", "aws_encryption_sdk_performance_tests", "__init__.py") + return VERSION_RE.search(init).group(1) + + +setup( + name="aws-encryption-sdk-performance-tests", + packages=find_packages("src"), + package_dir={"": "src"}, + author="Amazon Web Services", + maintainer="Amazon Web Services", + author_email="aws-cryptools@amazon.com", + url="https://github.com/awslabs/aws-encryption-sdk-python", + description="Performance tests for the AWS Encryption SDK for Python", + keywords="aws-encryption-sdk aws kms encryption", + license="Apache License 2.0", + version=get_version(), +) diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py new file mode 100644 index 000000000..cf1bf0fb4 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" +__version__ = "0.1.0" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py new file mode 100644 index 000000000..e846ec695 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py @@ -0,0 +1,131 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the AWS KMS keyring.""" + +import aws_encryption_sdk +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +def create_keyring( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = create_kms_client() + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def create_kms_client(aws_region="us-west-2"): + """Create an AWS KMS client. + + Usage: create_kms_client(aws_region) + :param aws_region: AWS region to use for KMS client. + :type aws_region: string + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + return kms_client + + +def create_keyring_given_kms_client( + kms_key_id: str, + kms_client: boto3.client, +): + """Demonstrate how to create an AWS KMS keyring with given KMS client. + + Usage: create_keyring(kms_key_id, kms_client) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + :param kms_client: boto3 client for KMS. + :type kms_client: boto3.client + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py new file mode 100644 index 000000000..a849b1a7f --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py @@ -0,0 +1,85 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw AES keyring.""" + +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..utils.util import PerfTestUtils + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + # We fix the static key in order to make the test deterministic + static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw AES keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py new file mode 100644 index 000000000..6eed281bd --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py @@ -0,0 +1,79 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw RSA keyring.""" +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + key_name_space = "Some managed raw keys" + key_name = "My 4096-bit RSA wrapping key" + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py new file mode 100644 index 000000000..c3136a5c7 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py @@ -0,0 +1,69 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the AWS KMS master key provider.""" + +import aws_encryption_sdk + + +def create_key_provider( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS master key-provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key-provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using an AWS KMS master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py new file mode 100644 index 000000000..42d071dcf --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py @@ -0,0 +1,101 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw AES master key provider.""" + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +from ..utils.util import PerfTestUtils + + +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Generates 256-bit keys for each unique key ID.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = "Some managed raw keys" + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Returns a static, randomly-generated symmetric key for the specified key ID. + + :param str key_id: Key ID + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw AES master key-provider. + + Usage: create_key_provider() + """ + # Create a Raw AES master key-provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = "My 256-bit AES wrapping key" + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw AES master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw AES master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py new file mode 100644 index 000000000..b52b78735 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py @@ -0,0 +1,101 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw RSA master key provider.""" + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + + +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Randomly generates and provides 4096-bit RSA keys consistently per unique key id.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = "Some managed raw keys" + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Retrieves a static, randomly generated, RSA key for the specified key id. + + :param str key_id: User-defined ID for the static key + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw RSA master key-provider. + + Usage: create_key_provider() + """ + # Create a Raw RSA master key-provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = "My 4096-bit RSA wrapping key" + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw RSA master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py new file mode 100644 index 000000000..52914b76a --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py @@ -0,0 +1,116 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Utility functions for AWS Encryption SDK performance tests.""" + + +class PerfTestUtils: + """Utility functions for AWS Encryption SDK performance tests.""" + DEFAULT_N_ITERS = 100 + DEFAULT_TESTING_N_ITERS = 1 + DEFAULT_FILE_SIZE = 'medium' + DEFAULT_AES_256_STATIC_KEY = \ + b'_\xcf"\x82\x03\x12\x9d\x00\x8a\xed\xaf\xe4\x80\x1d\x00t\xa6P\xac\xb6\xfe\xc5\xf6/{\xe7\xaaO\x01\x13W\x85' + DEFAULT_RSA_PUBLIC_KEY = bytes("-----BEGIN PUBLIC KEY-----\n" + + "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxwWEEtEofjwaoo3WO79D\n" + + "hntoPf2APlY5yzlqm6ZvMyaazlwetkAzLSn5GB4hjKZaf043BfADJEdwXMHn8/UN\n" + + "up0BfUj8PfGn/b8cL78CTnvFZd/7WxQh6tUnfLX7BMiccHMb9OHhRy5PrTSuj6Um\n" + + "wwhBadL+Lc23DGl2cyN9SjGuYWWQ1IHGFA4/2EQr+Ez4LpebZqwXgv0iLuApte1q\n" + + "vGl6zOhByxi1N/ORVEscLT82+L+F3STgeTYA1CaoLFQ0y9ybx+7UUfEfKxhGoGEO\n" + + "XEOTuRBdLE2Jm8xaBODLqfiXr0z62VhTpRs4CYYTGHTLFCJHqeH7R2fwvwoG1nIg\n" + + "QzWSyyapK7d5MLn3rF3ManjZhvlyHK1wqa7nWVpo+jq1Py+HWLAtU8FY0br6wnOR\n" + + "3jjPGk0N4//iDnxNN+kpDxFnHEvxe3eJKWnbw0GR9+BGj32O+wRMtGyfRTzkoD/E\n" + + "EqIRlDzdtYCAtFW0HUsdQwL+ssDjEQ0+lqvEQrwTU1WBZiBQhEmzksAowHAcNIT+\n" + + "Fz7mvIlpEETNOQbsJkoXdEkhJXljh5UYmH1cB5al1MJf/5ea5Xb2HfH5WkMy4+eS\n" + + "V68V+tXv3ZthTe2bCk9rQTH9FWKLIYJyZfv8WAIxSWEEsyk5b+7WUGmvtm/nPJ4Z\n" + + "RfzkXoBJqJiSiPYCM0+jG4sCAwEAAQ==\n" + + "-----END PUBLIC KEY-----\n", 'utf-8') + + DEFAULT_RSA_PRIVATE_KEY = bytes("-----BEGIN PRIVATE KEY-----\n" + + "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\n" + + "A/DHJmMI5bKETJyj1GhBE9LqypAI1Bo=\n" + + "-----END PRIVATE KEY-----\n", "utf-8") + + DEFAULT_ENCRYPTION_CONTEXT = { + "tenant": "TenantA", + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + DEFAULT_BRANCH_KEY_ID_A = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' + + DEFAULT_BRANCH_KEY_ID_B = '8ba79cef-581c-4125-9292-b057a29d42d7' + + @staticmethod + def read_file(filename): + """Returns the contents of the file.""" + with open(filename, 'rb') as file: + return file.read() + + @staticmethod + def get_rsa_key_from_file(filename): + """Returns the RSA key""" + with open(filename, "r", encoding='utf-8') as f: + key = f.read() + + # Convert the key from a string to bytes + key = bytes(key, 'utf-8') + + return key + + @staticmethod + def write_time_list_to_csv(time_list, filename): + """Writes the time list to a CSV file.""" + with open(filename + '.csv', 'w', encoding='utf-8') as myfile: + for time in time_list: + myfile.write(str(time) + '\n') diff --git a/performance_tests/test/keyrings/__init__.py b/performance_tests/test/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/keyrings/test_aws_kms_keyring.py b/performance_tests/test/keyrings/test_aws_kms_keyring.py new file mode 100644 index 000000000..950a2a82e --- /dev/null +++ b/performance_tests/test/keyrings/test_aws_kms_keyring.py @@ -0,0 +1,206 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the AWS KMS keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.aws_kms_keyring import ( + create_keyring, + create_keyring_given_kms_client, + create_kms_client, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_kms_keyring(): + """Click group helper function""" + + +@create_kms_keyring.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_create') +def create( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def create_kms_keyring_given_kms_client(): + """Click group helper function""" + + +@create_kms_keyring_given_kms_client.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_create_given_kms_client') +def create_given_kms_client( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + kms_client = create_kms_client() + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring_given_kms_client(kms_key_id, kms_client) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_kms_keyring(): + """Click group helper function""" + + +@encrypt_kms_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_kms_keyring(): + """Click group helper function""" + + +@decrypt_kms_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/kms/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +kms_keyring_test = click.CommandCollection(sources=[create_kms_keyring, + create_kms_keyring_given_kms_client, + encrypt_kms_keyring, + decrypt_kms_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_kms_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_create_given_kms_client(runner): + """Test the create_keyring_given_kms_client function""" + result = runner.invoke(create_kms_keyring_given_kms_client.commands['create-given-kms-client'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_kms_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_kms_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + kms_keyring_test() diff --git a/performance_tests/test/keyrings/test_raw_aes_keyring.py b/performance_tests/test/keyrings/test_raw_aes_keyring.py new file mode 100644 index 000000000..1e1da428a --- /dev/null +++ b/performance_tests/test/keyrings/test_raw_aes_keyring.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw AES keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.raw_aes_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_aes_keyring(): + """Click group helper function""" + + +@create_raw_aes_keyring.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_aes_keyring(): + """Click group helper function""" + + +@encrypt_raw_aes_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_aes_keyring(): + """Click group helper function""" + + +@decrypt_raw_aes_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_aes/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_aes_keyring_test = click.CommandCollection(sources=[create_raw_aes_keyring, + encrypt_raw_aes_keyring, + decrypt_raw_aes_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_raw_aes_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_raw_aes_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_raw_aes_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_aes_keyring_test() diff --git a/performance_tests/test/keyrings/test_raw_rsa_keyring.py b/performance_tests/test/keyrings/test_raw_rsa_keyring.py new file mode 100644 index 000000000..476701ac0 --- /dev/null +++ b/performance_tests/test/keyrings/test_raw_rsa_keyring.py @@ -0,0 +1,163 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw RSA keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.raw_rsa_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_rsa_keyring(): + """Click group helper function""" + + +@create_raw_rsa_keyring.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(public_key, private_key) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_rsa_keyring(): + """Click group helper function""" + + +@encrypt_raw_rsa_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(public_key, private_key) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_rsa_keyring(): + """Click group helper function""" + + +@decrypt_raw_rsa_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_rsa/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(public_key, private_key) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_rsa_keyring_test = click.CommandCollection(sources=[create_raw_rsa_keyring, + encrypt_raw_rsa_keyring, + decrypt_raw_rsa_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_raw_rsa_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_raw_rsa_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_raw_rsa_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_rsa_keyring_test() diff --git a/performance_tests/test/master_key_providers/__init__.py b/performance_tests/test/master_key_providers/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/master_key_providers/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py new file mode 100644 index 000000000..b869245b5 --- /dev/null +++ b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py @@ -0,0 +1,165 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the AWS KMS Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.aws_kms_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_kms_key_provider(): + """Click group helper function""" + + +@create_kms_key_provider.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_create') +def create( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider(kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_kms_key_provider(): + """Click group helper function""" + + +@encrypt_kms_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_kms_key_provider(): + """Click group helper function""" + + +@decrypt_kms_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/kms/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +kms_key_provider_test = click.CommandCollection(sources=[create_kms_key_provider, + encrypt_kms_key_provider, + decrypt_kms_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_kms_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_kms_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_kms_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + kms_key_provider_test() diff --git a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py new file mode 100644 index 000000000..375eca2ef --- /dev/null +++ b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw AES Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.raw_aes_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_aes_key_provider(): + """Click group helper function""" + + +@create_raw_aes_key_provider.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_aes_key_provider(): + """Click group helper function""" + + +@encrypt_raw_aes_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_aes_key_provider(): + """Click group helper function""" + + +@decrypt_raw_aes_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_aes/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_aes_key_provider_test = click.CommandCollection(sources=[create_raw_aes_key_provider, + encrypt_raw_aes_key_provider, + decrypt_raw_aes_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_raw_aes_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_raw_aes_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_raw_aes_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_aes_key_provider_test() diff --git a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py new file mode 100644 index 000000000..5d6db861a --- /dev/null +++ b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw RSA Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.raw_rsa_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_rsa_key_provider(): + """Click group helper function""" + + +@create_raw_rsa_key_provider.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_rsa_key_provider(): + """Click group helper function""" + + +@encrypt_raw_rsa_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_rsa_key_provider(): + """Click group helper function""" + + +@decrypt_raw_rsa_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_rsa/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_rsa_key_provider_test = click.CommandCollection(sources=[create_raw_rsa_key_provider, + encrypt_raw_rsa_key_provider, + decrypt_raw_rsa_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_raw_rsa_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_raw_rsa_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_raw_rsa_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_rsa_key_provider_test() diff --git a/performance_tests/test/resources/__init__.py b/performance_tests/test/resources/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/resources/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..18f1696874059d7bc64600dfae68f89a2a262f9e GIT binary patch literal 587 zcmZQ#typC1*|SBNH>m&Yq8iz2~2yypTmG|C1r-_NVh0;u#njL=(%4b(4!K z3rg~J3rdr6GLv<)Q!5!<94)ky%KZWg(o-#5z0520vs?^=!i=IS(j85c%~JF7GQxvB zEz14;OFb%#!m*9;5@mrPl^_`QtcOP}rqd-u%c-y*`m zz))vU!^WxA=F#?@myw-qLB2sQ6C;B`211O{K#q+wq0NIam6?T6&p?ocr}KZ(hSe`K z7P;)|=wf0NXs{NjFR|-v581ub%aHqAxQDC6)a4CM)6QNze!z1>v%vb9>jbTwPESkj zyFAzGjMzkroSHpLbx&<*{9>%%!ouHU>2x zTIZp7RIqJRuj$>%SL+|lc^kQY%BN#Tbp8VY(CLgo3)1 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct new file mode 100644 index 0000000000000000000000000000000000000000..076926bfb29ea579b6decde9b556366fc845ec1b GIT binary patch literal 8619 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 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct new file mode 100644 index 0000000000000000000000000000000000000000..a954c7134cf35f43723c446ecd912460ba8213ec GIT binary patch literal 4587 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 we9;}@ZG7#r6P~g^U}Pv#&+rQUwB+T{+ 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 UqpSaVSDwuHE*52Gm|5trYCM)!R{#J2 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct b/performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct new file mode 100644 index 0000000000000000000000000000000000000000..e62387249c756424277b3029e6db0ad58591826f GIT binary patch literal 4454 zcmV-s5t;4+1$Yw{{ts}sCFsTUNLf1Af0V}r7mhVx!S`DW(lB|@hF$<)0096MVRv&a zV{&qK~c4BQyZ&gDwYjIabLV7P`NmFBTLUTAqM`|@fQ%E^+ zYeP|TLn~!YHa1CBG&E^tW_36@a$ATl*JEn;bOAVEb_Aa`n+afB*mh35S`Ee(a(p5CW@-b(;NU_S^ zKn&jZ$cEFi5mSqAdIvo&c@Wg&3v`d@N{&2yxJ#TG3Atx98IX2}Kecc7EAI$D-;)hz z&bzZ;cTxBNHP=1KEa02|WDA+;L0Eev7!y4Qm>yeG6fz*a1|n#4b0M=gMV=$(t>HwE z-xcj=S<>i+qKzHVs9H&U5qEOlOKFO^=lP*2*J`}_lzudtDXbXIj{{e^!ouQIlc+{q zgYV|`ei-&#cDnbYm~msNFi72Z(%pI0f)vim0&(pC=)}WOClhfs`*OATpPoG9;IcWF z%s}Af^jL>U&WbSAm;B8BWA`?(#u4YnxRaC+c-|P`jHAxqArpC2R6U)pH%i%KrBA!c z5j#DJkmFBJ)pNK;(Wc%?D?xpE~?#jaj(97#%DZrLneeu2+ z|9aN$8JbAWN&hL0UXgU-^Q1A~^`u@UKX`Dy+!DOVTE!N&ycjs)%gZZ-GYLd-7APnv zBOTqA!cYIuaJn}on8^kCiLR6-4l*Eoqni1OQ8W{bu##N#ij**kr~*B_B{+!WSyTSw zw9y;Vv5|>ROL^*uA66?Z5r1!zkmSGlt(0Js;4|BGk3fz~sG=kN4bD;9_W=+)uj%7t zQip?zg|Ac^7OPw;O1IsuaLse1p?>U7`XF%nGXD20fi1CouMAb#qSBK|YxU}LO-Unn z{}z4GU7}34c@ZZ^xkFqT3z>AF&~|$%ptYjPDA4&YeS-t+&C>2jIW-bHHvV@xMm*LX zG8m|vZqTeJsl!EhZJxMJ7D<*sED#5q#Q57h$P$AytX()zKT5 zw(T3KtP&=yAQtTZV(~i4l-af7^ESRWXl&aF8`0m5o={|asP!~$m517{H0$)ydUX2w4wOQyMd9mz#kyqy$E-fMbV+#t0W*80uva;;Z@MK$#>hAyEU%@dmb6Z88W5BUQ|%ie6T{UNTl-N6o$3Cu@0qp0 z?jhQ8LoJI82bK>~Hj%gGCW>}Y_Kyg+Kc5cGRkGtpgvPdrlN(WPZB@nrK$It~Emfy= z&6eCIEr*GO4I_9IvL2u|DM05nWeCtoqyWNTxdkGH3bq|FA&xsGBQrgdn>Pc7g)l+( ze=?$K9@CoUD0X8^&@g#sh+uJj(o`8Jb0|DDED6#VY;UTKR2Niu!qNB{2?*h=)96zZ zdF-)L)9FqFlDc4Z(mlIq*|8i>CERA^uQl1iXml``U|{?H;z|POI26`s8p!kkOGoou ze?NpX9S{wA#yxk&mDJ-=_ZdDhrn;dGfk9JVK7%HMU$b~G%25}#FFO%}qg=1=L=%g; zL1TYa)859m6qj;T0F^9GS@P$Sg*}2tCsL12*nZ5U(| zZ8{bd73?1K#vJCFPIBACyE)%ssik#6`+O6bk_C^frCr|ID!Nn|b2kfN=sK?#Ucjg4 z9wf&+XJWu-Qc|N@^xyok>@$48RgvPJWf>Ld;EL(O5e&0uG`;DYcHxy0hkWeGDy1wQ z3BTEynsRyK--^u+k;oH*VcmkEXdC;HNPi_+%F3;P3e_b%Bvrr&Ybh$4-G$ewxPBi#HO4_BF;#*6dHnk}C)y`pQ_CjH)ZeJ*jvDpFA+t7U62w=3=|n4J zqs(9e=8!jwOPOQ3P>alUakD+x%6xBtcHlksxZ3;uvAgYe!Zd+kFX-O!t`ev-t5ItTEmpbkgnuBXY%}Mg z#*Vo1*~_L|fJ~vCCXOC%ErE=rt^$=60rYSd-$QSL(>MQCR{myRSUZ;vGpX>A)3rZn zQ|P$8N(OrE+$wLIu|+NP7|*zLIet zLo4pyuTtf&$NOeOyZ$4r9#SOUvLCNbOEFQF1>ATcA0Hwrridb-XxXEp0}me!|r-i6kAVz62Ak z`8q~(!e7dAXj;QrM+!Y~*zJ-!t?Rh@S>r*>Ia!GDGm>@CjK1=5pIDc=*aPMBkwtaj zQbLj_PWNpJm-Wu$DDN|zLXF=b%Ey)e68?^7$M7G~yk0pty{ zVeWd?H>--Wpz162w*`9blE)^KVTTOsb8T_5$P} zv?>jGvNT{}xeI})I$*aGQ*uJ+jJqF1Li_Nf--qaQ1{?U7jrZ1*TtjV@(|i zYj?(wd-=amVS;=;X)?q++&0R+`W88dVGi+=&t+a96{yGLCSGsdhA_SL;rPj(+1Wxb z{lQOmjjQMD>6lbCQA{ZnSBt;y>td(yP<;-L7z+RGq1C?c%n1|bWx~1ll)3-yQfEoU zRXd~-{QDZ~AJu^XsOs+=`9xz~^IC8mcd1Bfy21ppx{g=hjrpW1{+At3{tr9I3Sdd}!gf1k zknVAcdcvdmWb)8VWF`Tp2hi}cMVY7!)3A=;5f;@#mwW-AR{%j9MWZ6(8TBC~nf*-s zaMM60Pp77i!F&u8boM|)g`{mFPkDFE-dt!>Wba$SCr=n-pl1(j<P5xLdFtE*jeE-0JwKxHhkY;_~KCw z-{QA=GY3YPi(PCu-bZ7%f}gg3p&z}-nIozn&m+_1T#V~TBP`v>B1Houn${gbEnb&J z6B}@q{`F1)uyWvMe#88#XA&(6BuC28Hys=gPsTR2NOBQIS(PH9%kvCpIMalFqD1Jv zwOmC^I|8;4NCNxo_3d*_>vTt$92s~cD)Uh6M68$&&R&i49!yH5MzTjuDNco~c#D(& zLpSxvEqOOylKgS$d)fmlFw-z0Ubd*5wK%ptn|(HnDY+mf9%s2uCYw-$i0dg+O!Ey7 zRiVLuQA$kRxd%$|ZPk?vUFJ|7#SSJ5!+I{x&p=e(_2}N*geP;Dckfp^3YpYE#4@b} zu;VOfVfd8?D5;(=A)3ktA^LFoLp>6BI~%;Qm5k{o;udFQHUITU0GJSLzY*n1!xqkg z7#Yz6iavDk$2*bq0TZXQR^P@$609)rhho`Z9z12lQI z^8H4;$TyeU$Y0bRLr`_5_O=dfweZ;)SIkc}pkE-NKbNT#KOKxgZWQI-^8aVf-4Mo# zJ4|Drkqa-&bL!K78!WqBS9(l!d*iU@{Qcq*?FyZI{5KHKYC&T8Rql{?|G#Wx6ItUY zyE0wy5E^M;=aQh_A5`4ve0XeUZh~SDMY25H_UBXD1edZ%Lm_LfLMLccNcE*1LGNV|iXzHzuhb*hMxHt6919WL%6I?6~1pOrBI)DZV!}NtQ9-bIh14nNA7^bpZVHb-%0B0~|0xTZee@l;HH_$Qh*i$n3l+R&|PRunpy8Oka`IEu@)gOA3_&ctyWGt`R+-Ecm_rW(Zup%-Q=Rm zf|7jQg3_d%%w*l{)Jg^yM>D^m($Fwt{enoB(g;HXXA6^vuu`w^aEqk8^w1Qyie#5c zpI{>|@1%5>D36j%BV(s<{{k~_|IlO)ud)J*f^u71knzF!xv2`diFt|XsVNFYiRB7F z(~BAOeJd4=OwDwYGD{R3U4s?MixLY8GV{_wvJ4Ci4M5EE<(GoTms>X?V=ppxGZ;*q zx&D9niFehe8NpYjyW|)a_pXzVIQno`+qDnNWPTL22_@Zlz}L1>`Q*E`m!?!zzh+`! z5Ma0z>>Ct+k@LDf-!!Ku$KG8qoseo|6Y}?8dnebwbDq}hrxMx!AO1B@&DP)k?5Ar1 zQU8GeXf-1c!vKh_vax2#ku`4}4`gh4r}^A%-wizj4Gz)2XLi3yxy~cINdK;uz~5~r zY4yzk4A^*|@o!#QZ7_3s9`H}7EfxUcjmj(l literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..202643e9a47c3d902e31641767e837dbab65aaaa GIT binary patch literal 899 zcmV-}1AP1f1$a;k*Y6C|%Vu~O9PME8#TMGv-D56&of(URe4oUhO)&sp0096MVRv&a zV{&qK~dUZK(NlRj9I7%>bPEKiKNH=6ectT_^S4Ar}YDY3h zD`rGTX*5}6c5G-yWi(-7M=>ixVMc3Xd16;raCJ&yQ9V5X0RRVQ_G1Zf78CWqASsUpQlUu^)lm4R@Xf z3()wGI&o41BK?E3)<7oi^$-i}~GmK=OFN?HzBcx4;+(`3b@*q0?IB4*n5? z>9V$X=XZUpek$EzX&HROH09VgaGQY%PeoC{IMv&rDxyR(gC9tKIdcJ!@x9>?NU2ma zxF6|b+RLMB%Uu1@*L|9USt6u}NFiZL5ZQBwY*X;@T_-}I1%b{ZJP6cwyD$Du0}6Ub3(Gb$GZz}CX7^U? zN6SYN#JbaH(HM@Ffm?F5W|bxjOR}~7>e$$X8WnblyBzJYuidn-vzg@u#OcHqJEXRrfQ8q!b*QKi36DF~>EC^s z5>($+#m=(GPG46}z^aY*wc^nS&YJnlT2#!}-$qum)QPd>;_>sNL%y{O{{ktH;aBa0 zj8;i|0kc`yjGG7Wnit~6)?RL>tS9|^enhQy*94~+0ssII0I8@V{w5l%yy=9znPr}4 z(CW?RNfD!_?Vwv%cmW|R^O-LUpXR@Mp4PBCzlA6xXaE2I{{R300RR910000000000 z0RR910PvOk%5-wF>4(^>4Dnz@AOL4DWdbn(nI{|Z=WlyJzsROUf%}!7NJDYF5tf_- za^SO;L`WdC%_g6;r^9HSV{j@1$F+cl0x*4r?|Sl{+298nR<-|k#Esi>(tjA=Y#&$k Z4Q=Y&cGne<@Mn1}3)%96i?ANx>G00Sq__Y8 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct b/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct new file mode 100644 index 0000000000000000000000000000000000000000..259d83ea5ae956148020b4f61061e0932dfc0d6e GIT binary patch literal 8931 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 J#Rbn%t$1*ovReQE literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/plaintext/plaintext-data-empty.dat b/performance_tests/test/resources/plaintext/plaintext-data-empty.dat new file mode 100644 index 000000000..e69de29bb diff --git a/performance_tests/test/resources/plaintext/plaintext-data-large.dat b/performance_tests/test/resources/plaintext/plaintext-data-large.dat new file mode 100644 index 000000000..22bad9f3f --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-large.dat @@ -0,0 +1,21 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et netus et malesuada fames. Bibendum enim facilisis gravida neque convallis. Tortor consequat id porta nibh venenatis cras. Lacus sed viverra tellus in hac habitasse platea dictumst. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Risus pretium quam vulputate dignissim suspendisse in. Ante in nibh mauris cursus mattis molestie a iaculis at. Nulla porttitor massa id neque aliquam vestibulum morbi blandit. Urna et pharetra pharetra massa massa ultricies mi quis. Leo duis ut diam quam nulla porttitor massa id. Vitae suscipit tellus mauris a diam maecenas sed enim ut. + +Non nisi est sit amet facilisis magna etiam tempor. Mi bibendum neque egestas congue quisque egestas diam in arcu. Volutpat est velit egestas dui id ornare arcu odio ut. Amet tellus cras adipiscing enim eu turpis egestas. Tortor dignissim convallis aenean et tortor at risus viverra. Interdum consectetur libero id faucibus nisl tincidunt eget. In eu mi bibendum neque egestas congue quisque egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Leo vel orci porta non pulvinar. Amet massa vitae tortor condimentum. Malesuada fames ac turpis egestas maecenas pharetra. Feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Quam elementum pulvinar etiam non quam lacus. Accumsan in nisl nisi scelerisque eu ultrices. Pretium aenean pharetra magna ac placerat vestibulum. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Amet venenatis urna cursus eget nunc scelerisque viverra mauris in. Penatibus et magnis dis parturient montes nascetur ridiculus mus mauris. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. + +Leo a diam sollicitudin tempor id. Tempor orci eu lobortis elementum nibh. Sit amet commodo nulla facilisi nullam vehicula. Hendrerit gravida rutrum quisque non tellus. Diam vulputate ut pharetra sit. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Tortor vitae purus faucibus ornare. Risus viverra adipiscing at in tellus integer. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Facilisis sed odio morbi quis commodo odio aenean sed. At auctor urna nunc id. Ac tortor vitae purus faucibus ornare suspendisse sed nisi. Suspendisse interdum consectetur libero id faucibus nisl. Tellus id interdum velit laoreet id. Mus mauris vitae ultricies leo integer. Metus vulputate eu scelerisque felis imperdiet proin. + +Venenatis cras sed felis eget velit aliquet sagittis id. Turpis cursus in hac habitasse. Magna fringilla urna porttitor rhoncus dolor purus non. In tellus integer feugiat scelerisque varius morbi. Tortor consequat id porta nibh venenatis cras sed. Ut sem viverra aliquet eget sit amet tellus cras. Semper risus in hendrerit gravida. Libero enim sed faucibus turpis in. Ultricies leo integer malesuada nunc vel risus commodo. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Varius duis at consectetur lorem donec massa sapien faucibus et. Ornare arcu dui vivamus arcu felis bibendum ut tristique et. + +Diam quis enim lobortis scelerisque fermentum dui faucibus in. Cursus mattis molestie a iaculis at erat. Diam sit amet nisl suscipit adipiscing. Ultrices dui sapien eget mi proin sed libero. Purus ut faucibus pulvinar elementum integer enim neque. Ultricies mi quis hendrerit dolor magna eget. Morbi tincidunt ornare massa eget. Mauris cursus mattis molestie a iaculis at erat pellentesque. Phasellus vestibulum lorem sed risus. Sodales ut etiam sit amet nisl purus in. Habitant morbi tristique senectus et netus et. Consectetur lorem donec massa sapien faucibus et molestie. + +Montes nascetur ridiculus mus mauris vitae ultricies. Lectus urna duis convallis convallis. Pulvinar proin gravida hendrerit lectus. Semper auctor neque vitae tempus quam pellentesque nec. Donec pretium vulputate sapien nec. Id aliquet lectus proin nibh nisl. Enim ut sem viverra aliquet eget sit amet tellus. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Feugiat vivamus at augue eget arcu dictum varius. Venenatis tellus in metus vulputate eu. Aliquam vestibulum morbi blandit cursus risus at ultrices mi tempus. Id venenatis a condimentum vitae. Lorem mollis aliquam ut porttitor leo a diam sollicitudin tempor. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis. + +Nisi scelerisque eu ultrices vitae. Eu feugiat pretium nibh ipsum consequat nisl vel pretium. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Sit amet cursus sit amet dictum. Fermentum iaculis eu non diam. Quis imperdiet massa tincidunt nunc pulvinar. Tempor commodo ullamcorper a lacus vestibulum sed. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Vulputate mi sit amet mauris commodo quis imperdiet massa. Non nisi est sit amet facilisis magna etiam tempor orci. Consectetur libero id faucibus nisl tincidunt eget nullam. Sit amet risus nullam eget felis eget nunc. Aliquet porttitor lacus luctus accumsan. Vitae congue eu consequat ac felis donec. Vehicula ipsum a arcu cursus vitae congue mauris rhoncus. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. + +Massa eget egestas purus viverra. Nunc sed augue lacus viverra vitae congue eu consequat. Lectus quam id leo in. Augue eget arcu dictum varius duis. Nulla facilisi cras fermentum odio eu feugiat pretium. Adipiscing diam donec adipiscing tristique risus. Imperdiet dui accumsan sit amet. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. Dolor sit amet consectetur adipiscing elit duis. In fermentum et sollicitudin ac orci phasellus egestas tellus rutrum. Ridiculus mus mauris vitae ultricies leo integer malesuada. Nulla pharetra diam sit amet nisl. Nec dui nunc mattis enim ut tellus. Morbi non arcu risus quis varius quam quisque. Ac auctor augue mauris augue neque gravida in fermentum et. Morbi tincidunt augue interdum velit euismod. Sem viverra aliquet eget sit amet tellus cras adipiscing enim. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. Odio facilisis mauris sit amet. Amet mattis vulputate enim nulla aliquet. + +Nisi vitae suscipit tellus mauris a diam maecenas sed enim. Venenatis urna cursus eget nunc scelerisque viverra. Neque egestas congue quisque egestas diam in. Adipiscing vitae proin sagittis nisl. Sodales neque sodales ut etiam sit. Non consectetur a erat nam at. Ac felis donec et odio. Adipiscing tristique risus nec feugiat in fermentum posuere urna. Ultrices in iaculis nunc sed augue lacus viverra vitae. Enim sit amet venenatis urna. Amet consectetur adipiscing elit pellentesque. + +Venenatis a condimentum vitae sapien pellentesque. Ut faucibus pulvinar elementum integer enim neque. Nisl nunc mi ipsum faucibus vitae aliquet. Netus et malesuada fames ac. Et odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Ut diam quam nulla porttitor massa id. Id donec ultrices tincidunt arcu non sodales neque sodales ut. Viverra ipsum nunc aliquet bibendum enim. Lacus vestibulum sed arcu non odio. Lobortis mattis aliquam faucibus purus in massa tempor. Tortor at auctor urna nunc id cursus metus aliquam eleifend. Ornare suspendisse sed nisi lacus sed viverra tellus in. Tristique magna sit amet purus gravida quis. At ultrices mi tempus imperdiet nulla malesuada. Erat imperdiet sed euismod nisi. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. Fermentum dui faucibus in ornare quam viverra orci sagittis. Nec dui nunc mattis enim ut tellus elementum sagittis. + +Suspendisse interdum consectetur libero id faucibus nisl. Bibendum enim facilisis gravida neque convallis. Nisi vitae suscipit tellus mauris a. Massa ultricies mi quis hendreri. \ No newline at end of file diff --git a/performance_tests/test/resources/plaintext/plaintext-data-medium.dat b/performance_tests/test/resources/plaintext/plaintext-data-medium.dat new file mode 100644 index 000000000..3313ba519 --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-medium.dat @@ -0,0 +1,11 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et netus et malesuada fames. Bibendum enim facilisis gravida neque convallis. Tortor consequat id porta nibh venenatis cras. Lacus sed viverra tellus in hac habitasse platea dictumst. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Risus pretium quam vulputate dignissim suspendisse in. Ante in nibh mauris cursus mattis molestie a iaculis at. Nulla porttitor massa id neque aliquam vestibulum morbi blandit. Urna et pharetra pharetra massa massa ultricies mi quis. Leo duis ut diam quam nulla porttitor massa id. Vitae suscipit tellus mauris a diam maecenas sed enim ut. + +Non nisi est sit amet facilisis magna etiam tempor. Mi bibendum neque egestas congue quisque egestas diam in arcu. Volutpat est velit egestas dui id ornare arcu odio ut. Amet tellus cras adipiscing enim eu turpis egestas. Tortor dignissim convallis aenean et tortor at risus viverra. Interdum consectetur libero id faucibus nisl tincidunt eget. In eu mi bibendum neque egestas congue quisque egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Leo vel orci porta non pulvinar. Amet massa vitae tortor condimentum. Malesuada fames ac turpis egestas maecenas pharetra. Feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Quam elementum pulvinar etiam non quam lacus. Accumsan in nisl nisi scelerisque eu ultrices. Pretium aenean pharetra magna ac placerat vestibulum. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Amet venenatis urna cursus eget nunc scelerisque viverra mauris in. Penatibus et magnis dis parturient montes nascetur ridiculus mus mauris. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. + +Leo a diam sollicitudin tempor id. Tempor orci eu lobortis elementum nibh. Sit amet commodo nulla facilisi nullam vehicula. Hendrerit gravida rutrum quisque non tellus. Diam vulputate ut pharetra sit. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Tortor vitae purus faucibus ornare. Risus viverra adipiscing at in tellus integer. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Facilisis sed odio morbi quis commodo odio aenean sed. At auctor urna nunc id. Ac tortor vitae purus faucibus ornare suspendisse sed nisi. Suspendisse interdum consectetur libero id faucibus nisl. Tellus id interdum velit laoreet id. Mus mauris vitae ultricies leo integer. Metus vulputate eu scelerisque felis imperdiet proin. + +Venenatis cras sed felis eget velit aliquet sagittis id. Turpis cursus in hac habitasse. Magna fringilla urna porttitor rhoncus dolor purus non. In tellus integer feugiat scelerisque varius morbi. Tortor consequat id porta nibh venenatis cras sed. Ut sem viverra aliquet eget sit amet tellus cras. Semper risus in hendrerit gravida. Libero enim sed faucibus turpis in. Ultricies leo integer malesuada nunc vel risus commodo. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Varius duis at consectetur lorem donec massa sapien faucibus et. Ornare arcu dui vivamus arcu felis bibendum ut tristique et. + +Diam quis enim lobortis scelerisque fermentum dui faucibus in. Cursus mattis molestie a iaculis at erat. Diam sit amet nisl suscipit adipiscing. Ultrices dui sapien eget mi proin sed libero. Purus ut faucibus pulvinar elementum integer enim neque. Ultricies mi quis hendrerit dolor magna eget. Morbi tincidunt ornare massa eget. Mauris cursus mattis molestie a iaculis at erat pellentesque. Phasellus vestibulum lorem sed risus. Sodales ut etiam sit amet nisl purus in. Habitant morbi tristique senectus et netus et. Consectetur lorem donec massa sapien faucibus et molestie. + +Montes nascetur ridiculus mus mauris vitae ultricies. Lectus urna duis convallis convallis. Pulvinar pr. \ No newline at end of file diff --git a/performance_tests/test/resources/plaintext/plaintext-data-small.dat b/performance_tests/test/resources/plaintext/plaintext-data-small.dat new file mode 100644 index 000000000..b8475e61f --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-small.dat @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consect. \ No newline at end of file diff --git a/performance_tests/tox.ini b/performance_tests/tox.ini new file mode 100644 index 000000000..1b7d073aa --- /dev/null +++ b/performance_tests/tox.ini @@ -0,0 +1,215 @@ +[tox] +envlist = + # The performance tests only work for python 3.11 and 3.12 + py{311,312}-performance_tests-mpl + bandit, doc8 + ; {flake8, pylint}{,-tests}, + isort-check, black-check, + # prone to false positives + vulture + +# Additional test environments: +# +# linters :: Runs all linters over all source code. +# linters-tests :: Runs all linters over all tests. + +# Autoformatter helper environments: +# +# autoformat : Apply all autoformatters +# +# black-check : Check for "black" issues +# blacken : Fix all "black" issues +# +# isort-seed : Generate a known_third_party list for isort. +# NOTE: make the "known_third_party = " line in setup.cfg before running this +# NOTE: currently it incorrectly identifies this library too; make sure you remove it +# isort-check : Check for isort issues +# isort : Fix isort issues + +# Operational helper environments: +# +# build :: Builds source and wheel dist files. +# test-release :: Builds dist files and uploads to testpypi pypirc profile. +# release :: Builds dist files and uploads to pypi pypirc profile. + +[testenv:base-command] +commands = pytest test/ +deps = + click + + +[testenv] +passenv = + # Pass through AWS credentials + AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \ + # AWS Role access in CodeBuild is via the contaner URI + AWS_CONTAINER_CREDENTIALS_RELATIVE_URI \ + # Pass through AWS profile name (useful for local testing) + AWS_PROFILE +sitepackages = False +deps = + -rrequirements.txt + # Install the MPL requirements if the `-mpl` suffix is present + mpl: -rrequirements_mpl.txt + .. +commands = + performance_tests: {[testenv:base-command]commands} + +[testenv:blacken-src] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = + black --line-length 120 \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + test/ \ + {posargs} + +# Linters +[testenv:flake8] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = + flake8 \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + {posargs} + +[testenv:flake8-tests] +basepython = {[testenv:flake8]basepython} +deps = -r../dev_requirements/linter-requirements.txt +commands = + flake8 \ + # Ignore F811 redefinition errors in tests (breaks with pytest-mock use) + # E203 is not PEP8 compliant https://github.com/ambv/black#slices + # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators + --ignore F811,E203,W503,D \ + test/ + +[testenv:pylint] +basepython = python3 +deps = + -r../dev_requirements/linter-requirements.txt +commands = + pylint \ + --rcfile=pylintrc \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + {posargs} + +[testenv:pylint-tests] +basepython = {[testenv:pylint]basepython} +deps = {[testenv:pylint]deps} +commands = + pylint \ + --rcfile=pylintrc \ + test/ \ + {posargs} + +[testenv:blacken] +basepython = python3 +deps = + {[testenv:blacken-src]deps} +commands = + {[testenv:blacken-src]commands} + +[testenv:black-check] +basepython = python3 +deps = + {[testenv:blacken]deps} +commands = + {[testenv:blacken-src]commands} --diff + +[testenv:isort-seed] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = seed-isort-config + +[testenv:isort] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = isort -rc \ + src \ + test \ + setup.py \ + {posargs} + +[testenv:isort-check] +basepython = python3 +deps = {[testenv:isort]deps} +commands = {[testenv:isort]commands} -c + +[testenv:autoformat] +basepython = python3 +deps = + {[testenv:blacken]deps} + {[testenv:isort]deps} + .. +commands = + {[testenv:blacken]commands} + {[testenv:isort]commands} + +[testenv:doc8] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = doc8 README.rst + +[testenv:readme] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = python setup.py check -r -s + +[testenv:bandit] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = bandit -r src/aws_encryption_sdk_performance_tests/ + +[testenv:linters] +basepython = python3 +deps = + {[testenv:flake8]deps} + {[testenv:pylint]deps} + {[testenv:doc8]deps} + {[testenv:readme]deps} + {[testenv:bandit]deps} +commands = + {[testenv:flake8]commands} + {[testenv:pylint]commands} + {[testenv:doc8]commands} + {[testenv:readme]commands} + {[testenv:bandit]commands} + +# Release tooling +[testenv:park] +basepython = python3 +skip_install = true +deps = -r../dev_requirements/release-requirements.txt +commands = python setup.py park + +[testenv:build] +basepython = python3 +skip_install = true +deps = + -r../dev_requirements/release-requirements.txt +commands = + python setup.py sdist bdist_wheel + +[testenv:test-release] +basepython = python3 +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository testpypi dist/* + +[testenv:release] +basepython = python3 +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository pypi dist/* From 39d449883c230a008238a139306085abf90e633c Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:57:34 -0700 Subject: [PATCH 14/51] chore(performance_tests): added hierarchy keyring and caching cmm tests (#686) --- .../keyrings/hierarchy_keyring.py | 128 ++++++++++++ .../keyrings/raw_aes_keyring.py | 1 - .../aws_kms_master_key_provider.py | 8 +- .../master_key_providers/caching_cmm.py | 85 ++++++++ .../raw_aes_master_key_provider.py | 10 +- .../raw_rsa_master_key_provider.py | 10 +- .../utils/util.py | 4 +- .../test/keyrings/test_hierarchy_keyring.py | 174 +++++++++++++++++ .../test_aws_kms_master_key_provider.py | 2 +- .../master_key_providers/test_caching_cmm.py | 183 ++++++++++++++++++ .../test_raw_aes_master_key_provider.py | 2 +- .../test_raw_rsa_master_key_provider.py | 2 +- .../caching_cmm/ciphertext-data-empty.ct | Bin 0 -> 587 bytes .../caching_cmm/ciphertext-data-large.ct | Bin 0 -> 8619 bytes .../caching_cmm/ciphertext-data-medium.ct | Bin 0 -> 4587 bytes .../caching_cmm/ciphertext-data-small.ct | Bin 0 -> 623 bytes .../hierarchy/ciphertext-data-empty.ct | Bin 0 -> 654 bytes .../hierarchy/ciphertext-data-large.ct | Bin 0 -> 8686 bytes .../hierarchy/ciphertext-data-medium.ct | Bin 0 -> 4654 bytes .../hierarchy/ciphertext-data-small.ct | Bin 0 -> 690 bytes 20 files changed, 588 insertions(+), 21 deletions(-) create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py create mode 100644 performance_tests/test/keyrings/test_hierarchy_keyring.py create mode 100644 performance_tests/test/master_key_providers/test_caching_cmm.py create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-small.ct diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py new file mode 100644 index 000000000..b1bdc6913 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py @@ -0,0 +1,128 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the hierarchy keyring.""" + +import aws_encryption_sdk +import boto3 +from aws_cryptographic_materialproviders.keystore import KeyStore +from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig +from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CacheTypeDefault, + CreateAwsKmsHierarchicalKeyringInput, + DefaultCache, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..utils.util import PerfTestUtils + + +def create_keyring( + key_store_table_name: str, + logical_key_store_name: str, + kms_key_id: str, + branch_key_id: str = PerfTestUtils.DEFAULT_BRANCH_KEY_ID +): + """Demonstrate how to create a hierarchy keyring. + + Usage: create_keyring(key_store_table_name, logical_key_store_name, kms_key_id, branch_key_id) + :param key_store_table_name: Name of the KeyStore DynamoDB table. + :type key_store_table_name: string + :param logical_key_store_name: Logical name of the KeyStore. + :type logical_key_store_name: string + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + :param branch_key_id: Branch key you want to use for the hierarchy keyring. + :type branch_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create boto3 clients for DynamoDB and KMS. + ddb_client = boto3.client('dynamodb', region_name="us-west-2") + kms_client = boto3.client('kms', region_name="us-west-2") + + # Configure your KeyStore resource. + # This SHOULD be the same configuration that you used + # to initially create and populate your KeyStore. + keystore: KeyStore = KeyStore( + config=KeyStoreConfig( + ddb_client=ddb_client, + ddb_table_name=key_store_table_name, + logical_key_store_name=logical_key_store_name, + kms_client=kms_client, + kms_configuration=KMSConfigurationKmsKeyArn( + value=kms_key_id + ), + ) + ) + + # Create the Hierarchical Keyring. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id=branch_key_id, + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a hierarchy keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a hierarchy keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring, + encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py index a849b1a7f..a2a3c9ab1 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py @@ -19,7 +19,6 @@ def create_keyring(): key_name_space = "Some managed raw keys" key_name = "My 256-bit AES wrapping key" - # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits # We fix the static key in order to make the test deterministic static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py index c3136a5c7..023cd5942 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py @@ -8,7 +8,7 @@ def create_key_provider( kms_key_id: str ): - """Demonstrate how to create an AWS KMS master key-provider. + """Demonstrate how to create an AWS KMS master key provider. Usage: create_key_provider(kms_key_id) :param kms_key_id: KMS Key identifier for the KMS key you want to use. @@ -17,7 +17,7 @@ def create_key_provider( For more information on KMS Key identifiers, see https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id """ - # Create a KMS master key-provider. + # Create a KMS master key provider. key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ kms_key_id, ]) @@ -29,7 +29,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using an AWS KMS master key-provider. + """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -51,7 +51,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using an AWS KMS master key-provider. + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py new file mode 100644 index 000000000..7199c50bf --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py @@ -0,0 +1,85 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Caching Cryptographic Materials Manager (CMM) with KMS Master Key Provider.""" + +import aws_encryption_sdk + + +def create_cmm( + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int +): + """Demonstrate how to create a Caching CMM. + + Usage: create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + :param kms_key_id: Amazon Resource Name (ARN) of the KMS customer master key + :type kms_key_id: str + :param max_age_in_cache: Maximum time in seconds that a cached entry can be used + :type max_age_in_cache: float + :param cache_capacity: Maximum number of entries to retain in cache at once + :type cache_capacity: int + """ + # Security thresholds + # Max messages (or max bytes per) data key are optional + max_messages_encrypted = 100 + + # Create a master key provider for the KMS customer master key (CMK) + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_id]) + + # Create a local cache + cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity) + + # Create a caching CMM + caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager( + master_key_provider=key_provider, + cache=cache, + max_age=max_age_in_cache, + max_messages_encrypted=max_messages_encrypted, + ) + + return caching_cmm + + +def encrypt_using_cmm( + plaintext_data: bytes, + caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager +): + """Demonstrate how to encrypt plaintext data using a Caching CMM. + + Usage: encrypt_using_cmm(plaintext_data, caching_cmm) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param caching_cmm: Crypto Materials Manager to use for encryption. + :type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + materials_manager=caching_cmm + ) + + return ciphertext_data + + +def decrypt_using_cmm( + ciphertext_data: bytes, + caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager +): + """Demonstrate how to decrypt ciphertext data using a Caching CMM. + + Usage: decrypt_using_cmm(ciphertext_data, caching_cmm) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param caching_cmm: Crypto Materials Manager to use for encryption. + :type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + materials_manager=caching_cmm + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py index 42d071dcf..de0188c5e 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py @@ -43,13 +43,13 @@ def _get_raw_key(self, key_id): def create_key_provider(): - """Demonstrate how to create a Raw AES master key-provider. + """Demonstrate how to create a Raw AES master key provider. Usage: create_key_provider() """ - # Create a Raw AES master key-provider. + # Create a Raw AES master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings key_id = "My 256-bit AES wrapping key" key_provider = StaticRandomMasterKeyProvider() key_provider.add_master_key(key_id) @@ -61,7 +61,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using a Raw AES master key-provider. + """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -83,7 +83,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using a Raw AES master key-provider. + """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py index b52b78735..cdbe24110 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py @@ -43,13 +43,13 @@ def _get_raw_key(self, key_id): def create_key_provider(): - """Demonstrate how to create a Raw RSA master key-provider. + """Demonstrate how to create a Raw RSA master key provider. Usage: create_key_provider() """ - # Create a Raw RSA master key-provider. + # Create a Raw RSA master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings key_id = "My 4096-bit RSA wrapping key" key_provider = StaticRandomMasterKeyProvider() key_provider.add_master_key(key_id) @@ -61,7 +61,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using a Raw RSA master key-provider. + """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -83,7 +83,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using a Raw RSA master key-provider. + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py index 52914b76a..9100ef12e 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py @@ -87,9 +87,7 @@ class PerfTestUtils: "the data you are handling": "is what you think it is", } - DEFAULT_BRANCH_KEY_ID_A = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' - - DEFAULT_BRANCH_KEY_ID_B = '8ba79cef-581c-4125-9292-b057a29d42d7' + DEFAULT_BRANCH_KEY_ID = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' @staticmethod def read_file(filename): diff --git a/performance_tests/test/keyrings/test_hierarchy_keyring.py b/performance_tests/test/keyrings/test_hierarchy_keyring.py new file mode 100644 index 000000000..e890c2a18 --- /dev/null +++ b/performance_tests/test/keyrings/test_hierarchy_keyring.py @@ -0,0 +1,174 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the hierarchy keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.hierarchy_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_hierarchy_keyring(): + """Click group helper function""" + + +@create_hierarchy_keyring.command() +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_create') +def create( + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_hierarchy_keyring(): + """Click group helper function""" + + +@encrypt_hierarchy_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_hierarchy_keyring(): + """Click group helper function""" + + +@decrypt_hierarchy_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/hierarchy/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +hierarchy_keyring_test = click.CommandCollection(sources=[create_hierarchy_keyring, + encrypt_hierarchy_keyring, + decrypt_hierarchy_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_hierarchy_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_hierarchy_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_hierarchy_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + hierarchy_keyring_test() diff --git a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py index b869245b5..c7b665857 100644 --- a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the AWS KMS Master key-provider.""" +"""This is a performance test for creating the AWS KMS Master key provider.""" import os import time diff --git a/performance_tests/test/master_key_providers/test_caching_cmm.py b/performance_tests/test/master_key_providers/test_caching_cmm.py new file mode 100644 index 000000000..f8552f96e --- /dev/null +++ b/performance_tests/test/master_key_providers/test_caching_cmm.py @@ -0,0 +1,183 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating a Caching CMM.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.caching_cmm import ( + create_cmm, + decrypt_using_cmm, + encrypt_using_cmm, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_caching_cmm(): + """Click group helper function""" + + +@create_caching_cmm.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_create') +def create( + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the create_cmm function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_caching_cmm(): + """Click group helper function""" + + +@encrypt_caching_cmm.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_cmm function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + caching_cmm = create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_cmm(plaintext_data, caching_cmm) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_caching_cmm(): + """Click group helper function""" + + +@decrypt_caching_cmm.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/caching_cmm/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_cmm function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + caching_cmm = create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_cmm(ciphertext_data, caching_cmm) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +caching_cmm_test = click.CommandCollection(sources=[create_caching_cmm, + encrypt_caching_cmm, + decrypt_caching_cmm]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_cmm function""" + result = runner.invoke(create_caching_cmm.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_cmm function""" + result = runner.invoke(encrypt_caching_cmm.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_cmm function""" + result = runner.invoke(decrypt_caching_cmm.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + caching_cmm_test() diff --git a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py index 375eca2ef..cf39963bf 100644 --- a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the Raw AES Master key-provider.""" +"""This is a performance test for creating the Raw AES Master key provider.""" import os import time diff --git a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py index 5d6db861a..63b00a0e3 100644 --- a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the Raw RSA Master key-provider.""" +"""This is a performance test for creating the Raw RSA Master key provider.""" import os import time diff --git a/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..5bfb39a4ef910764c629a850f8f51b4631306ee9 GIT binary patch literal 587 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 V-X-*L3)Ww3h#M2;#hI&ZLd6QKdcyz! literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct b/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct new file mode 100644 index 0000000000000000000000000000000000000000..63dac90b7e752819bd5740db6d3f7d3a3cb73a65 GIT binary patch literal 623 zcmZQ#t+=k}wKe7Pg1*9K(sA3qFHtz?I*0eWX1hk=@r;>w_SWxWh-YAA5KSyE)=e&| zEGWs>EhtUO$xPPGPOW5caWvPj3`>b9Eh@}$3QjX9^>lVkinKH{tSs|!^U5?Sa&#{7 ztTa!IOwIB4&36j&aQ8_oG&Rlg&oS2yC`oqHcX70}1scx|GCn)En87=-D9;MWu>x|e zN{e;NQ;SPMHB~WkNP7HcRa02?-eQSQNEN?w`lp z4|5KyO#D!C+apI}G|Om=?aWx{i|wE zRLcrKli9d#?UkG-U;a{~S zkJTGO@9vR2(6qNp?xnok;r~lx&htKhW98{NuW_^8{*rmq-DW&tNH<7jGVs!B&^7YR zIqQ45-#?rCY{JPW7kd(I96X$d)4F<%OUxL$&g{W+`Wy7 y`)l`{P%)ijlvKB4V)ON&#}N^=x) zQ%e$45=#;pxKi`Lwr1w%F|a4+=ar;ZlrXSm7AxfC1L@+_yhyOc;Z6n2cwOfmXx)W2k>~wK4xNI5MT(Mto1Wc_{SZg9~tG&wZ1X8B^Ca< zI(?q}XJ3rXQa$tMsj*R)y;h~qIQe(Y(QEQ5o&SM=fdS|z1OT(|we0+ROKt1TAb01N z43D4ZFr*u#G8r)DuF;8~-?QM);oy+ZC*)`JvDNDS&wAIZ-2PHiaNXA{@&y7$&~r~RHY%?PsUW~ PN2N7q=$;rmEe^6F+=&Sg_E%s8Iyvjc~z_FjqK~D_BfWYA{k&K}l;_G;wWFYHLMlWm;HJb3;T*cSUt^ zRC!KVR(3BmL@;)AR8cT#MPf^1Zc<`SICE)lZ)8$PXFWXt2x4_~AYo)=a{v!@b7f|A zY#?oAbYWy+bYTDrWo~0~d2n=TZ*BkwV{dMBWq5P|25EC3Zf|q|26JU&a%FS?26Sa^ zVQzE)2UKNlVQzFm01$Mp z01;t#b1iFab1i6TWpZJ1V`zB*Bw;l&WM*MuWGy#jVq`5eG&3+QVKHW8En#9|VKp*2 zIb>llHvn8qVEAa6K9sGyWr*f{FZg&AR}+tCM2x~(uKn;4t4M8;{z}-JQb7~4l}}(U z`sQKxm(sm6%L5KaMcTDHcu-*>lUVZB)Fg|xxs}%`>eQLTsAJDC4qYKnZr`o~000mG zJY(`y*ayl12Ign5os^h3)<)WSvQY0iw!xUJY}hZ4!m9YJRl+dsmnQJoGe6#Yq`nL7!9DNfOdn zs$wRt^|ith=xKvVI8|T_-bKDLds+&=*r-jVL-lpQJ_!2LuCsY!HwpWT@9{V*mwMCo z-FS2EJ&aQq#j^#|DRmaW7X>r}FpW`|O>0J(Bke~Q$~ajPRmXCYUMc$KwMeytFcxMc zpGe!)=Lhc3p99KiLwTn%AWdwNMxaE_fBh@V7GAeIcMX#NBiEvw?Z`b@7!=jR@xnyT zRqaV?5{;LdC!v;42m8ewJavyPtM5V;sNyrmieoWPEyLb6=`mH@VJMU0kF+i;Cxca$ z(H_2eT6F22BS&(e*QUY+3tE({YV1PF@0#R8#@6=idl=;_1zWo1$`ns#k2H_9gm8ON z8gZDacwY&8x}a2aO=d1%EFR`=7j*sgzk<7}jj`+8Ngg%z6Shi&4rftH8tV7eFCuVN z?!cj)+ELdrI$iBZ8bWpCChNq5>6NuB-yiBcR1WwJAc^@7)EeBy#o*xF#Boo z4d{snP8&rsXl!oEEC08>^z@ssZ`B+mt}F?fDay^Z=h(`wx>kc<(oStm9IHnv2fs0= zQj>2^TjwC;^fu@O)Uask8eoBc`y?^|Lfos8NL`q5x=LIHE>6glDOM@!N+@La_V+(_ znK~Akd@AR?K_oNSZh==qDKsM%gK0eJtCw_n9<%6S?&Zxa|0^5K$tm&J;Ddps{fN+E zqPe~hw$s|{obnC@;HgK`N>e6mG25B?$wjG`Ff+y|lpqy$D&d0=WLMF zRzwjCyCNJkj zU38v8f@0F{3=A*)iG&Cib$FaBIqA@p5jpSP8{$z=w01@N&3gX$<5Nl-j^5%aazR9L z4(6}Ny^#5Ti(jsq=V%R#yEy@wlc7}(V5=`q;I{oqtTo&JRo4V=(^U4Y!aXBLKbGWr z4x)hL|B40g-%6xnnfXs79qzW_-et^-1!jHh+$6IqkGCU_bg2WvR}d;Ge*ab)X2>Bh zbaS(d#IdV`rahE%8Ioz3y1l(dAObyg?cQ`T++%6#lt}R83GiWQc&%zJ`v!e z(mIhpVv3-ED}s#8!;?ZSTU_KGv|H`1ci7rnzd8yo;rdwv$Nei4_U3q>3>GV2o>*AA zI>lD<^e7wYdGJZUo+h)O)tq!A|>NHWH&3`EQ5s!R2u9~P+Vz&8^lrFQQ z|FMFH10*U(5_nao0wwCdPD~vCd0-JH{!qM#MRYi0p{8?js?ls@x@o?v2hj+ZNXkc0#NNUz zbJLk(%bR4<>Dne1)M4s2C`*OZEn^$A%IZt7oc`L!%aP^MfDMnBqYa^)2u>NI3>fuZ4RU5R?XE$fervux>fbr2XZvp zk*K5v5U|K!3`R!C@&O-1;I!#BuaT*{?P5kt;0~-YI0Z9Gy-mUn)zn$Ww>dk*fXkAI zOzEIn-ll={!QPyd@Fg&Zw+6sI#EwQ6GsL6M7)x=2mFx`lWtJ7RMSMFvDqUXnLW!rP z=>amwMB35AVgM~0SQ@?dF$A~CjH(6XtA3+VvsD`DH>$VMCdsr=Afd0VM)(Ynpc6G^ z-FQ64hx7Q@T}1!byt0~nl&3@FW-cGsx6npev4Q)&bSBh1Ugdm9}Yk|@acEIj6=VV zg9+AnYcA3P6%95qj104jHcf;;p!)&uk9EKMnbO51XodVoO2^o~5X>K!hzN++<*t`T zauPtltyIEIy3k%kFlWBW&&2i6rMhMNU3}+o9~0?$g^fUyaSP#n+ZCYKd~8z9!W-;) zjbO)E-yuhdbvduBWQskB4~F-57{Z}v>r_+K4Je6m{kr*-7W^3TZJQa<6%5uX--9HW zyYwL6d*}PJS`9xlM@LDYW&jwy4~vQ)?eF*m+o!Xx#GI-AURd&kKm@U)A9$-}5baL^ zjdBIGA)?6wM{o&n943r<&eY`muV%cUZRK2lw`<21r8W%rd7UyzL~!NHcb80Pnq$^o zoJ(0qV7?nheE8?F2VM>cm=gh#JUNm%`Lu}}Iy*=>kPn_KO@SlcIrV3vWY*$S7G9-~ zm1)tgxczsQc_zl!BW|nR93%z{Y(o$}l&Ftl`W%!ji>V#LCX2aTjDw@2TM?)fCnEz{l_IN6sVQ$6M9(%!K}}_CD)7=Htt^c+@o`dLMNmJS|qmouNg@@ z`CeypQ?&LU%_z+HW7;M@$Pp+XHG!u#1+LV|HHewGNfGuPQ5g^k1dH*7MloS6QBM#bQ2C*WP7HE>+z#2xYQrIsK(?sJX86c7ee$Ut1J zWCrj9Sco-Sf8m;|GLS9{u!8$yiTAMg8W0-Mp9r69c|-#JnZq#z!q+3sWnuyIEqE-` zPgU{gC#9rI9wE5-YEjx0t#-c{Sc2;emFZ871{6^=-E-~0N{xcgC6V0O7Xr8p=ujfq zO((KIpiH{)V0s8C46}Jo#n%GQx1w8+q9M+MlY(dkv8o~SbxgNk$~znV=wmp+u$tcz z`s$g$y1kPCM1b2;LzEu%t$cL3s4}irxVGPj6;}wTnY7X@d+A`@&g8*Q}{@R8o*7yp1`S6(acAY)oq}>++64u!t(}m!~)h9-u!0BLJiMDcL zgdwshO27{LpT`_YRE${Rgi-o)o-RTLfgo?f2G!8o*2p$y+h3zx_)=)YjCU#P+-He< zjFg;u2UwkEH7L>pMnL8aK?VVF+?kaYPC@k+y@5J1kc+dujN!daqOmAg_KwIN{dUe~ z!rz@aJ=BDXtCLxJQQ7OTJ)lx7fQ)q*pKm^-PO_L3;Q55(PDvW$+b=HLBM z*AOWJqnyAx@5Caqa$bx%;p@OPDM$HjUAMFx+vih&Q^e^NG$S7!T#VCog?S&m?2DA>Su-mvM}%6r9H0}l2#mOdmv$Jz>~64DDUhdjIG)w# zTOjyIoD(>$n#d=iM5rLBj^b#-@i{eqJnFRJHm(* zLuel+1BFLB;09L*TVkUesVjKIjeeC#%sMa~&Nd$h%to`}UCn_YK&@glbf^NtP!p~+ z8HNp=tD?+4^B8O4-~1x0km0)U6@hPb7kja&i^rzwwo>&xw|4FL(QXY5y7jIVq65>1 zO2X`tIIoR0P!kZewzz+W;vBxvyg-E^XqVh9N}kc{K_ z6C~qX3p6NBmSL^!w|>R%Xw#S+jRRVgWW_S}x^tQU%o1>2H-q-_H}+ooA^&4vPxITEiN=cJC=R3RmFp5tll4zV{KYYx`p zz3_i9vxGG5H|qs_1iMNwbdmT^g8Os0RB?||qh_Yge`vrANjU5yQ7gxayNfwS#1-(S zcsL)h_i4}G&*c+-yhR~JX|n%zzyB{DhB|9tB-kzs>{6SVRd|dfHAM zam82-0u3$cN(A~SgIWULqZw2t5zMUC*~Z3MRzGZ$mA-RM39|rU{17aDi+;-$4vPml zL3(wWPaSdlr}AY@=#HO7ZEGDf+Q4^ch1h7WSl9Tre`$9R4Q5&%`My>y76-l-Qc57& z8f%&agM;CQ9M)>$kZQdA#Nxq%Qd|*-8uVTQjJk<=6+rft5reBwwioDSAO9_`LVcwn zv9OEgQ|(UAjABK7y6qk&ZN|0Um@bS0+qyGPod%bR0I+m91Nb*@sJKJFO63y@=-o;_ z`3#-)(+D6bCb#hSYdi25|NsC000002000000000000002000j_PxC#|DmeW}osYQQ zEA6i9va~G0`044K3o@z)jg+?m>XcPt1r-ADKq$zzH_-;i@s#LP&|jg=h4pU%#EPQ@ z838#s9Mu&R+(ywP>}!0PpO{oWQcY$!5p*Aq)uU)d6*1mYuvfK2qBvMB79N^L-I$Qs zo3683)S6MUDyEUapiLSUZ>Wl_E8t07fH~)Z4

JYO(+TJbO_}u7^|V49O9TF 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 B55NEb literal 0 HcmV?d00001 From 3476816c644a6d85f4ead68aa6f07acc3a0feffa Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:58:52 -0700 Subject: [PATCH 15/51] =?UTF-8?q?chore(migration=20examples):=20added=20KM?= =?UTF-8?q?S,=20raw=20AES=20and=20raw=20RSA=20keyring/MKP=E2=80=A6=20(#687?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/src/migration/README.rst | 19 ++ .../migration_aws_kms_key_example.py | 166 +++++++++++ .../migration_raw_aes_key_example.py | 207 ++++++++++++++ .../migration_raw_rsa_key_example.py | 259 ++++++++++++++++++ ...migration_set_commitment_policy_example.py | 0 examples/test/migration/__init__.py | 3 + .../test_i_migration_aws_kms_key_example.py | 16 ++ .../test_i_migration_raw_aes_key_example.py | 15 + .../test_i_migration_raw_rsa_key_example.py | 15 + ...migration_set_commitment_policy_example.py | 2 +- 10 files changed, 701 insertions(+), 1 deletion(-) create mode 100644 examples/src/migration/README.rst create mode 100644 examples/src/migration/migration_aws_kms_key_example.py create mode 100644 examples/src/migration/migration_raw_aes_key_example.py create mode 100644 examples/src/migration/migration_raw_rsa_key_example.py rename examples/src/{ => migration}/migration_set_commitment_policy_example.py (100%) create mode 100644 examples/test/migration/__init__.py create mode 100644 examples/test/migration/test_i_migration_aws_kms_key_example.py create mode 100644 examples/test/migration/test_i_migration_raw_aes_key_example.py create mode 100644 examples/test/migration/test_i_migration_raw_rsa_key_example.py rename examples/test/{ => migration}/test_i_migration_set_commitment_policy_example.py (83%) diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst new file mode 100644 index 000000000..41d3f5515 --- /dev/null +++ b/examples/src/migration/README.rst @@ -0,0 +1,19 @@ +################## +Migration Examples +################## + +The `Encryption SDK for Python`_ now uses the `AWS Cryptographic Material Providers Library`_. The MPL abstracts lower +level cryptographic materials management of encryption and decryption materials. + +This directory contains migration examples for: + +#. Moving to Keyrings from Master Key Providers: + * Migration example to AWS KMS keyring from AWS KMS Master Key Provider. + * Migration example to Raw AES keyring from Raw AES Master Key Provider. + * Migration example to Raw RSA keyring from Raw RSA Master Key Provider. + +#. Migration to newer versions of the ESDK (4.x+) from 1.x versions: + * Setting a 'CommitmentPolicy' during migration - If you have messages encrypted with 1.x versions of the ESDK (i.e. not using key commitment) and want to migrate to encrypt with key commitment using the keyring providers introduced in ESDK 4.x, this example will guide you on how to decrypt those messages using the new version of the ESDK. + +.. _AWS Cryptographic Material Providers Library: https://github.com/aws/aws-cryptographic-material-providers-library +.. _Encryption SDK for Python: https://github.com/aws/aws-encryption-sdk-python/tree/9c34aad60fc918c1a9186ec5215a451e8bfd0f65 \ No newline at end of file diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py new file mode 100644 index 000000000..28b8193e3 --- /dev/null +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -0,0 +1,166 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) + +The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and +decrypt data keys. This example creates a KMS Keyring and KMS MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + + +def create_keyring( + kms_key_id: str, + aws_region="us-west-2" +): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def create_key_provider( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS master key provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + +def migration_aws_kms_key( + kms_key_id: str +): + """Demonstrate a migration example for moving to an AWS KMS keyring from AWS KMS MKP. + + Usage: migration_aws_kms_key(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a AWS KMS Keyring + aws_kms_keyring = create_keyring(kms_key_id=kms_key_id) + + # 1b. Create a AWS KMS Master Key Provider + aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id) + + # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=aws_kms_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=aws_kms_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py new file mode 100644 index 000000000..772f83cf5 --- /dev/null +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -0,0 +1,207 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw AES Keyring from Raw AES master key provider (MKP) + +The Raw AES keyring lets you use an AES symmetric key that you provide as a wrapping key that +protects your data key. You need to generate, store, and protect the key material, +preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring +when you need to provide the wrapping key and encrypt the data keys locally or offline. + +This example creates a Raw AES Keyring and Raw AES MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both Raw AES keyring and Raw AES MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html +""" +import secrets + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +DEFAULT_AES_256_STATIC_KEY = secrets.token_bytes(32) + +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME = "My 256-bit AES wrapping key" + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + # We fix the static key in order to make the test deterministic + static_key = DEFAULT_AES_256_STATIC_KEY + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring + + +# This is a helper class necessary for the Raw AES master key provider +# In the StaticMasterKeyProvider, we fix the static key to +# DEFAULT_AES_256_STATIC_KEY in order to make the test deterministic. +# Thus, both the Raw AES keyring and Raw AES MKP have the same key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new random key for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): + """Generates 256-bit keys for each unique key ID.""" + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Returns a static, symmetric key for the specified key ID. + + :param str key_id: Key ID + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = DEFAULT_AES_256_STATIC_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw AES master key provider. + + Usage: create_key_provider() + """ + # Create a Raw AES master key provider. + + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + key_id = DEFAULT_KEY_NAME + key_provider = StaticMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def migration_raw_aes_key(): + """Demonstrate a migration example for moving to a Raw AES keyring from Raw AES MKP. + + Usage: migration_raw_aes_key() + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a Raw AES Keyring + raw_aes_keyring = create_keyring() + + # 1b. Create a Raw AES Master Key Provider + raw_aes_master_key_provider = create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_aes_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_aes_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py new file mode 100644 index 000000000..7c6020a53 --- /dev/null +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -0,0 +1,259 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw RSA Keyring from Raw RSA master key provider (MKP) + +The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory +with RSA public and private keys that you provide. In this example, we define the RSA keys to +encrypt and decrypt the data keys. + +You need to generate, store, and protect the private key, preferably in a +hardware security module (HSM) or key management system. +The encryption function encrypts the data key under the RSA public key. The decryption function +decrypts the data key using the private key. + +This example creates a Raw RSA Keyring and Raw RSA MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both Raw RSA keyring and Raw RSA MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + +For more information on how to use Raw RSA keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html +""" +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME = "My 4096-bit RSA wrapping key" + + +def generate_rsa_keys_helper(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys_helper() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +DEFAULT_RSA_PUBLIC_KEY, DEFAULT_RSA_PRIVATE_KEY = generate_rsa_keys_helper() + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring + + +# This is a helper class necessary for the Raw RSA master key provider. +# In the StaticMasterKeyProvider, we fix the static key to +# DEFAULT_RSA_PRIVATE_KEY in order to make the test deterministic. +# Thus, both the Raw RSA keyring and Raw RSA MKP have the same private_key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new random key pair for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): + """Provides 4096-bit RSA keys consistently per unique key id.""" + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Retrieves a static, RSA key for the specified key id. + + :param str key_id: User-defined ID for the static key + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + # Also, in practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + static_key = DEFAULT_RSA_PRIVATE_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw RSA master key provider. + + Usage: create_key_provider() + """ + # Create a Raw RSA master key provider. + + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + key_id = DEFAULT_KEY_NAME + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + key_provider = StaticMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def migration_raw_rsa_key( + public_key=DEFAULT_RSA_PUBLIC_KEY, + private_key=DEFAULT_RSA_PRIVATE_KEY +): + """Demonstrate a migration example for moving to a Raw RSA keyring from Raw RSA MKP. + + Usage: migration_raw_rsa_key(public_key, private_key) + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a Raw RSA Keyring + raw_rsa_keyring = create_keyring(public_key=public_key, private_key=private_key) + + # 1b. Create a Raw RSA Master Key Provider + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + raw_rsa_master_key_provider = create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_rsa_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_rsa_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py similarity index 100% rename from examples/src/migration_set_commitment_policy_example.py rename to examples/src/migration/migration_set_commitment_policy_example.py diff --git a/examples/test/migration/__init__.py b/examples/test/migration/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/migration/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py new file mode 100644 index 000000000..d4cf49ce9 --- /dev/null +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_aws_kms_key_example.""" +import pytest + +from ...src.migration.migration_aws_kms_key_example import ( + migration_aws_kms_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_aws_kms_key(): + """Test function for migration of AWS KMS Keys.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + migration_aws_kms_key(kms_key_id) diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py new file mode 100644 index 000000000..7601e7dc0 --- /dev/null +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_raw_aes_key_example.""" +import pytest + +from ...src.migration.migration_raw_aes_key_example import ( + migration_raw_aes_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_raw_aes_key(): + """Test function for migration of Raw AES keys.""" + migration_raw_aes_key() diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py new file mode 100644 index 000000000..9e111d25a --- /dev/null +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_raw_rsa_key_example.""" +import pytest + +from ...src.migration.migration_raw_rsa_key_example import ( + migration_raw_rsa_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_raw_rsa_key(): + """Test function for migration of Raw RSA keys.""" + migration_raw_rsa_key() diff --git a/examples/test/test_i_migration_set_commitment_policy_example.py b/examples/test/migration/test_i_migration_set_commitment_policy_example.py similarity index 83% rename from examples/test/test_i_migration_set_commitment_policy_example.py rename to examples/test/migration/test_i_migration_set_commitment_policy_example.py index afbc758bc..4620d64df 100644 --- a/examples/test/test_i_migration_set_commitment_policy_example.py +++ b/examples/test/migration/test_i_migration_set_commitment_policy_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_set_commitment_policy_example.""" import pytest -from ..src.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring +from ...src.migration.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] From fc8fd38ba1a6efa1ae2db109c890f7d6bccd225e Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:32:15 -0700 Subject: [PATCH 16/51] chore(custom_cmm_example.py): added test for custom_cmm_example.py (#690) --- examples/src/custom_mpl_cmm_example.py | 125 ++++++++++++++ ...cryptographic_materials_manager_example.py | 133 +++++++++++++++ examples/src/legacy/custom_cmm_example.py | 87 ++++++++++ examples/test/legacy/examples_test_utils.py | 2 +- .../test/legacy/test_i_custom_cmm_example.py | 51 ++++++ examples/test/legacy/v3_default_cmm.py | 159 ++++++++++++++++++ .../test_i_migration_aws_kms_key_example.py | 4 +- .../test_i_migration_raw_aes_key_example.py | 4 +- .../test_i_migration_raw_rsa_key_example.py | 4 +- .../test/test_i_custom_mpl_cmm_example.py | 39 +++++ ...cryptographic_materials_manager_example.py | 14 ++ tox.ini | 4 +- 12 files changed, 615 insertions(+), 11 deletions(-) create mode 100644 examples/src/custom_mpl_cmm_example.py create mode 100644 examples/src/default_cryptographic_materials_manager_example.py create mode 100644 examples/src/legacy/custom_cmm_example.py create mode 100644 examples/test/legacy/test_i_custom_cmm_example.py create mode 100644 examples/test/legacy/v3_default_cmm.py create mode 100644 examples/test/test_i_custom_mpl_cmm_example.py create mode 100644 examples/test/test_i_default_cryptographic_materials_manager_example.py diff --git a/examples/src/custom_mpl_cmm_example.py b/examples/src/custom_mpl_cmm_example.py new file mode 100644 index 000000000..544ca5f00 --- /dev/null +++ b/examples/src/custom_mpl_cmm_example.py @@ -0,0 +1,125 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Example to create a custom implementation of the MPL's ICryptographicMaterialsManager class and use it with the ESDK. + +The cryptographic materials manager (CMM) assembles the cryptographic materials that are used +to encrypt and decrypt data. The cryptographic materials include plaintext and encrypted data keys, +and an optional message signing key. + +Cryptographic Materials Managers (CMMs) are composable; if you just want to extend the behavior of +the default CMM, you can do this as demonstrated in this example. This is the easiest approach if +you are just adding a small check to the CMM methods, as in this example. + +If your use case calls for fundamentally changing aspects of the default CMM, you can also write +your own implementation without extending an existing CMM. The default CMM's implementation is a +good reference to use if you need to write a custom CMM implementation from scratch. +Custom implementations of CMMs must implement get_encryption_materials and decrypt_materials. + +For more information on a default implementation of a CMM, +please look at the default_cryptographic_materials_manager_example.py example. + +For more information on Cryptographic Material Managers, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager +""" + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, + SignatureAlgorithmNone, +) +from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + + +# Custom CMM implementation using the MPL. +# This CMM only allows encryption/decryption using signing algorithms. +# It wraps an underlying CMM implementation and checks its materials +# to ensure that it is only using signed encryption algorithms. +class MPLCustomSigningSuiteOnlyCMM(ICryptographicMaterialsManager): + """Example custom crypto materials manager class.""" + + def __init__(self, keyring: IKeyring, cmm: ICryptographicMaterialsManager = None) -> None: + """Constructor for MPLCustomSigningSuiteOnlyCMM class.""" + if cmm is not None: + self.underlying_cmm = cmm + else: + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create a CryptographicMaterialsManager for encryption and decryption + cmm_input: CreateDefaultCryptographicMaterialsManagerInput = \ + CreateDefaultCryptographicMaterialsManagerInput( + keyring=keyring + ) + + self.underlying_cmm: ICryptographicMaterialsManager = \ + mat_prov.create_default_cryptographic_materials_manager( + input=cmm_input + ) + + def get_encryption_materials(self, param): + """Provides encryption materials appropriate for the request for the custom CMM. + + :param aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsInput param: Input object to + provide to a crypto material manager's `get_encryption_materials` method. + :returns: Encryption materials output + :rtype: aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsOutput + """ + materials = self.underlying_cmm.get_encryption_materials(param) + if isinstance(materials.encryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): + raise ValueError( + "Algorithm provided to MPLCustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + str(materials.encryption_materials.algorithm_suite) + ) + return materials + + def decrypt_materials(self, param): + """Provides decryption materials appropriate for the request for the custom CMM. + + :param aws_cryptographic_materialproviders.mpl.models.DecryptMaterialsInput param: Input object to provide + to a crypto material manager's `decrypt_materials` method. + :returns: Decryption materials output + :rtype: aws_cryptographic_materialproviders.mpl.models.GetDecryptionMaterialsOutput + """ + materials = self.underlying_cmm.decrypt_materials(param) + if isinstance(materials.decryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): + raise ValueError( + "Algorithm provided to MPLCustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + str(materials.decryption_materials.algorithm_suite) + ) + return materials + + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_decrypt_with_cmm( + cmm: ICryptographicMaterialsManager +): + """Encrypts and decrypts a string using a custom CMM. + + :param ICryptographicMaterialsManager cmm: CMM to use for encryption and decryption + """ + # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a + # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. + client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + + # Encrypt the plaintext source data + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + materials_manager=cmm + ) + + # Decrypt the ciphertext + cycled_plaintext, _ = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext + assert cycled_plaintext == EXAMPLE_DATA diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py new file mode 100644 index 000000000..bfffc36d9 --- /dev/null +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -0,0 +1,133 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the default Cryptographic Material Managers (CMM). + +The default cryptographic materials manager (CMM) assembles the cryptographic materials +that are used to encrypt and decrypt data. The cryptographic materials include +plaintext and encrypted data keys, and an optional message signing key. +This example creates a CMM and then encrypts a custom input EXAMPLE_DATA +with an encryption context. Creating a CMM involves taking a keyring as input, +and we use an AWS KMS Keyring for this example. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on Cryptographic Material Managers, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsKeyringInput, + CreateDefaultCryptographicMaterialsManagerInput, +) +from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_default_cmm( + kms_key_id: str +): + """Demonstrate an encrypt/decrypt cycle using default Cryptographic Material Managers. + + Usage: encrypt_and_decrypt_with_default_cmm(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create a KMS keyring to use with the CryptographicMaterialsManager + kms_client = boto3.client('kms', region_name="us-west-2") + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # 4. Create a CryptographicMaterialsManager for encryption and decryption + cmm_input: CreateDefaultCryptographicMaterialsManagerInput = \ + CreateDefaultCryptographicMaterialsManagerInput( + keyring=kms_keyring + ) + + cmm: ICryptographicMaterialsManager = mat_prov.create_default_cryptographic_materials_manager( + input=cmm_input + ) + + # 5. Encrypt the data with the encryptionContext. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + materials_manager=cmm, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Decrypt your encrypted data using the same cmm you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/legacy/custom_cmm_example.py b/examples/src/legacy/custom_cmm_example.py new file mode 100644 index 000000000..07e8ca50b --- /dev/null +++ b/examples/src/legacy/custom_cmm_example.py @@ -0,0 +1,87 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Example to create a custom implementation of the native ESDK CryptoMaterialsManager class.""" + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy, StrictAwsKmsMasterKeyProvider +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager +from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager + + +# Custom CMM implementation. +# This CMM only allows encryption/decryption using signing algorithms. +# It wraps an underlying CMM implementation and checks its materials +# to ensure that it is only using signed encryption algorithms. +class CustomSigningSuiteOnlyCMM(CryptoMaterialsManager): + """Example custom crypto materials manager class.""" + + def __init__(self, master_key_provider: StrictAwsKmsMasterKeyProvider) -> None: + """Constructor for CustomSigningSuiteOnlyCMM class.""" + self.underlying_cmm = DefaultCryptoMaterialsManager(master_key_provider) + + def get_encryption_materials(self, request): + """Provides encryption materials appropriate for the request for the custom CMM. + + :param EncryptionMaterialsRequest request: Request object to provide to a + crypto material manager's `get_encryption_materials` method. + :returns: Encryption materials + :rtype: EncryptionMaterials + """ + materials = self.underlying_cmm.get_encryption_materials(request) + if not materials.algorithm.is_signing(): + raise ValueError( + "Algorithm provided to CustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + materials.algorithm + ) + return materials + + def decrypt_materials(self, request): + """Provides decryption materials appropriate for the request for the custom CMM. + + :param DecryptionMaterialsRequest request: Request object to provide to a + crypto material manager's `decrypt_materials` method. + """ + if not request.algorithm.is_signing(): + raise ValueError( + "Algorithm provided to CustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + request.algorithm + ) + return self.underlying_cmm.decrypt_materials(request) + + +def encrypt_decrypt_with_cmm( + cmm: CryptoMaterialsManager, + source_plaintext: str +): + """Encrypts and decrypts a string using a custom CMM. + + :param CryptoMaterialsManager cmm: CMM to use for encryption and decryption + :param bytes source_plaintext: Data to encrypt + """ + # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a + # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. + client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + + # Encrypt the plaintext source data + ciphertext, encryptor_header = client.encrypt( + source=source_plaintext, + materials_manager=cmm + ) + + # Decrypt the ciphertext + cycled_plaintext, decrypted_header = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext + assert cycled_plaintext == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes all key pairs from + # the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + # + # In production, always use a meaningful encryption context. In this sample, we omit the + # encryption context (no key pairs). + assert all( + pair in decrypted_header.encryption_context.items() for pair in encryptor_header.encryption_context.items() + ) diff --git a/examples/test/legacy/examples_test_utils.py b/examples/test/legacy/examples_test_utils.py index 3f877e301..8787e0f38 100644 --- a/examples/test/legacy/examples_test_utils.py +++ b/examples/test/legacy/examples_test_utils.py @@ -39,7 +39,7 @@ from integration_test_utils import ( # noqa pylint: disable=unused-import,import-error get_cmk_arn, - get_second_cmk_arn, get_mrk_arn, + get_second_cmk_arn, get_second_mrk_arn, ) diff --git a/examples/test/legacy/test_i_custom_cmm_example.py b/examples/test/legacy/test_i_custom_cmm_example.py new file mode 100644 index 000000000..397230090 --- /dev/null +++ b/examples/test/legacy/test_i_custom_cmm_example.py @@ -0,0 +1,51 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for encryption and decryption using custom CMM.""" +import botocore.session +import pytest + +import aws_encryption_sdk + +from ...src.legacy.custom_cmm_example import CustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm +from .examples_test_utils import get_cmk_arn, static_plaintext +from .v3_default_cmm import V3DefaultCryptoMaterialsManager + +pytestmark = [pytest.mark.examples] + + +def test_custom_cmm_example(): + """Test method for encryption and decryption using V3 default CMM.""" + plaintext = static_plaintext + cmk_arn = get_cmk_arn() + botocore_session = botocore.session.Session() + + # Create a KMS master key provider. + kms_kwargs = dict(key_ids=[cmk_arn]) + if botocore_session is not None: + kms_kwargs["botocore_session"] = botocore_session + master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) + + # Create the custom signing CMM using the master_key_provider + cmm = CustomSigningSuiteOnlyCMM(master_key_provider=master_key_provider) + + encrypt_decrypt_with_cmm(cmm=cmm, + source_plaintext=plaintext) + + +def test_v3_default_cmm(): + """Test method for encryption and decryption using V3 default CMM.""" + plaintext = static_plaintext + cmk_arn = get_cmk_arn() + botocore_session = botocore.session.Session() + + # Create a KMS master key provider. + kms_kwargs = dict(key_ids=[cmk_arn]) + if botocore_session is not None: + kms_kwargs["botocore_session"] = botocore_session + master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) + + # Create the V3 default CMM (V3DefaultCryptoMaterialsManager) using the master_key_provider + cmm = V3DefaultCryptoMaterialsManager(master_key_provider=master_key_provider) + + encrypt_decrypt_with_cmm(cmm=cmm, + source_plaintext=plaintext) diff --git a/examples/test/legacy/v3_default_cmm.py b/examples/test/legacy/v3_default_cmm.py new file mode 100644 index 000000000..f077e26c9 --- /dev/null +++ b/examples/test/legacy/v3_default_cmm.py @@ -0,0 +1,159 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Copy-paste of the V3 default CMM with small changes to pass linters.""" +import logging + +import attr + +from aws_encryption_sdk.exceptions import MasterKeyProviderError, SerializationError +from aws_encryption_sdk.identifiers import CommitmentPolicy +from aws_encryption_sdk.internal.crypto.authentication import Signer, Verifier +from aws_encryption_sdk.internal.crypto.elliptic_curve import generate_ecc_signing_key +from aws_encryption_sdk.internal.defaults import ALGORITHM, ALGORITHM_COMMIT_KEY, ENCODED_SIGNER_KEY +from aws_encryption_sdk.internal.str_ops import to_str +from aws_encryption_sdk.internal.utils import prepare_data_keys +from aws_encryption_sdk.internal.utils.commitment import ( + validate_commitment_policy_on_decrypt, + validate_commitment_policy_on_encrypt, +) +from aws_encryption_sdk.key_providers.base import MasterKeyProvider +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager + +_LOGGER = logging.getLogger(__name__) + + +@attr.s(hash=False) +class V3DefaultCryptoMaterialsManager(CryptoMaterialsManager): + """Copy of the default crypto material manager for ESDK V3. + + This is a copy-paste of the DefaultCryptoMaterialsManager implementation + from the V3 ESDK commit: 98b5eb7c2bd7d1b2a3380aacfa508e8721c4d8a9 + This CMM is used to explicitly assert that the V3 implementation of + the DefaultCMM is compatible with future version's logic, + which implicitly asserts that custom implementations of V3-compatible CMMs + are also compatible with future version's logic. + + :param master_key_provider: Master key provider to use + :type master_key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + + master_key_provider = attr.ib(validator=attr.validators.instance_of(MasterKeyProvider)) + +# pylint: disable=no-self-use + def _generate_signing_key_and_update_encryption_context(self, algorithm, encryption_context): + """Generates a signing key based on the provided algorithm. + + :param algorithm: Algorithm for which to generate signing key + :type algorithm: aws_encryption_sdk.identifiers.Algorithm + :param dict encryption_context: Encryption context from request + :returns: Signing key bytes + :rtype: bytes or None + """ + _LOGGER.debug("Generating signing key") + if algorithm.signing_algorithm_info is None: + return None + + signer = Signer(algorithm=algorithm, key=generate_ecc_signing_key(algorithm=algorithm)) + encryption_context[ENCODED_SIGNER_KEY] = to_str(signer.encoded_public_key()) + return signer.key_bytes() + + def get_encryption_materials(self, request): + """Creates encryption materials using underlying master key provider. + + :param request: encryption materials request + :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest + :returns: encryption materials + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises MasterKeyProviderError: if no master keys are available from the underlying master key provider + :raises MasterKeyProviderError: if the primary master key provided by the underlying master key provider + is not included in the full set of master keys provided by that provider + :raises ActionNotAllowedError: if the commitment policy in the request is violated by the algorithm being + used + """ + default_algorithm = ALGORITHM + if request.commitment_policy in ( + CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT, + CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT, + ): + default_algorithm = ALGORITHM_COMMIT_KEY + algorithm = request.algorithm if request.algorithm is not None else default_algorithm + + validate_commitment_policy_on_encrypt(request.commitment_policy, request.algorithm) + + encryption_context = request.encryption_context.copy() + + signing_key = self._generate_signing_key_and_update_encryption_context(algorithm, encryption_context) + + primary_master_key, master_keys = self.master_key_provider.master_keys_for_encryption( + encryption_context=encryption_context, + plaintext_rostream=request.plaintext_rostream, + plaintext_length=request.plaintext_length, + ) + if not master_keys: + raise MasterKeyProviderError("No Master Keys available from Master Key Provider") + if primary_master_key not in master_keys: + raise MasterKeyProviderError("Primary Master Key not in provided Master Keys") + + data_encryption_key, encrypted_data_keys = prepare_data_keys( + primary_master_key=primary_master_key, + master_keys=master_keys, + algorithm=algorithm, + encryption_context=encryption_context, + ) + + _LOGGER.debug("Post-encrypt encryption context: %s", encryption_context) + + return EncryptionMaterials( + algorithm=algorithm, + data_encryption_key=data_encryption_key, + encrypted_data_keys=encrypted_data_keys, + encryption_context=encryption_context, + signing_key=signing_key, + ) + +# pylint: disable=no-self-use + def _load_verification_key_from_encryption_context(self, algorithm, encryption_context): + """Loads the verification key from the encryption context if used by algorithm suite. + + :param algorithm: Algorithm for which to generate signing key + :type algorithm: aws_encryption_sdk.identifiers.Algorithm + :param dict encryption_context: Encryption context from request + :returns: Raw verification key + :rtype: bytes + :raises SerializationError: if algorithm suite requires message signing and no verification key is found + """ + encoded_verification_key = encryption_context.get(ENCODED_SIGNER_KEY, None) + + if algorithm.signing_algorithm_info is not None and encoded_verification_key is None: + raise SerializationError("No signature verification key found in header for signed algorithm.") + + if algorithm.signing_algorithm_info is None: + if encoded_verification_key is not None: + raise SerializationError("Signature verification key found in header for non-signed algorithm.") + return None + + verifier = Verifier.from_encoded_point(algorithm=algorithm, encoded_point=encoded_verification_key) + return verifier.key_bytes() + + def decrypt_materials(self, request): + """Obtains a plaintext data key from one or more encrypted data keys + using underlying master key provider. + + :param request: decrypt materials request + :type request: aws_encryption_sdk.materials_managers.DecryptionMaterialsRequest + :returns: decryption materials + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + validate_commitment_policy_on_decrypt(request.commitment_policy, request.algorithm) + + data_key = self.master_key_provider.decrypt_data_key_from_list( + encrypted_data_keys=request.encrypted_data_keys, + algorithm=request.algorithm, + encryption_context=request.encryption_context, + ) + verification_key = self._load_verification_key_from_encryption_context( + algorithm=request.algorithm, encryption_context=request.encryption_context + ) + + return DecryptionMaterials(data_key=data_key, verification_key=verification_key) diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py index d4cf49ce9..612a896ba 100644 --- a/examples/test/migration/test_i_migration_aws_kms_key_example.py +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_aws_kms_key_example.""" import pytest -from ...src.migration.migration_aws_kms_key_example import ( - migration_aws_kms_key, -) +from ...src.migration.migration_aws_kms_key_example import migration_aws_kms_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py index 7601e7dc0..d5e4f7789 100644 --- a/examples/test/migration/test_i_migration_raw_aes_key_example.py +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_raw_aes_key_example.""" import pytest -from ...src.migration.migration_raw_aes_key_example import ( - migration_raw_aes_key, -) +from ...src.migration.migration_raw_aes_key_example import migration_raw_aes_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py index 9e111d25a..238dcbaab 100644 --- a/examples/test/migration/test_i_migration_raw_rsa_key_example.py +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_raw_rsa_key_example.""" import pytest -from ...src.migration.migration_raw_rsa_key_example import ( - migration_raw_rsa_key, -) +from ...src.migration.migration_raw_rsa_key_example import migration_raw_rsa_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_custom_mpl_cmm_example.py b/examples/test/test_i_custom_mpl_cmm_example.py new file mode 100644 index 000000000..d98b6b6b9 --- /dev/null +++ b/examples/test/test_i_custom_mpl_cmm_example.py @@ -0,0 +1,39 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for encryption and decryption using custom CMM.""" +import boto3 +import pytest +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..src.custom_mpl_cmm_example import MPLCustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm + +pytestmark = [pytest.mark.examples] + + +def test_custom_cmm_example(): + """Test method for encryption and decryption using V3 default CMM.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + + # Create KMS keyring to use with the CMM + kms_client = boto3.client('kms', region_name="us-west-2") + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # Create the custom MPL signing CMM using the keyring + cmm = MPLCustomSigningSuiteOnlyCMM(keyring=kms_keyring) + + encrypt_decrypt_with_cmm(cmm=cmm) diff --git a/examples/test/test_i_default_cryptographic_materials_manager_example.py b/examples/test/test_i_default_cryptographic_materials_manager_example.py new file mode 100644 index 000000000..8a18f655d --- /dev/null +++ b/examples/test/test_i_default_cryptographic_materials_manager_example.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the default Cryptographic Materials Manager example.""" +import pytest + +from ..src.default_cryptographic_materials_manager_example import encrypt_and_decrypt_with_default_cmm + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_default_cmm(): + """Test function for encrypt and decrypt using the default Cryptographic Materials Manager example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_default_cmm(kms_key_id) diff --git a/tox.ini b/tox.ini index 9152f51a6..28be94a63 100644 --- a/tox.ini +++ b/tox.ini @@ -169,10 +169,12 @@ deps = {[testenv:flake8]deps} commands = flake8 examples/src/ flake8 \ - # Ingore D103 missing docstring errors in tests (test names should be self-documenting) + # Ignore D103 missing docstring errors in tests (test names should be self-documenting) # E203 is not PEP8 compliant https://github.com/ambv/black#slices # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators --ignore D103,E203,W503 \ + # copy-paste test for v3_default_cmm; intentionally not changing code + --per-file-ignores 'examples/test/legacy/v3_default_cmm.py: D205,D400,D401' \ examples/test/ [testenv:pylint] From fceb2b02d0446673471751456a4de42ab306d42b Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 30 Jul 2024 10:56:50 -0700 Subject: [PATCH 17/51] chore(MPL): Update README and primary pydocs (#658) --- README.rst | 284 +++++++----------- src/aws_encryption_sdk/__init__.py | 88 ++++-- .../internal/deprecation.py | 32 ++ 3 files changed, 204 insertions(+), 200 deletions(-) create mode 100644 src/aws_encryption_sdk/internal/deprecation.py diff --git a/README.rst b/README.rst index 6cd8c6824..fa6effb1f 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,12 @@ Required Prerequisites * boto3 >= 1.10.0 * attrs +Recommended Prerequisites +========================= + +* aws-cryptographic-material-providers: >= TODO.TODO.TODO (TODO-MPL: versionme) + * Requires Python 3.11+. + Installation ============ @@ -49,42 +55,71 @@ Installation .. code:: - $ pip install aws-encryption-sdk + $ pip install "aws-encryption-sdk[MPL]" +The `[MPL]` suffix also installs the `AWS Cryptographic Material Providers Library (MPL)`_. +This is a library that contains constructs for encrypting and decrypting your data. +We highly recommend installing the MPL. +However, if you do not wish to install the MPL, omit the `[MPL]` suffix. Concepts ======== -There are four main concepts that you need to understand to use this library: +There are three main concepts that you need to understand to use this library: + +Data Keys +--------- +Data keys are the encryption keys that are used to encrypt your data. If your algorithm suite +uses a key derivation function, the data key is used to generate the key that directly encrypts the data. + +Keyrings +-------- +Keyrings are resources that generate, encrypt, and decrypt data keys. +You specify a keyring when encrypting and the same or a different keyring when decrypting. + +Note: You must also install the `AWS Cryptographic Material Providers Library (MPL)`_ to create and use keyrings. + +For more information, see the `AWS Documentation for Keyrings`_. Cryptographic Materials Managers -------------------------------- Cryptographic materials managers (CMMs) are resources that collect cryptographic materials and prepare them for use by the Encryption SDK core logic. -An example of a CMM is the default CMM, which is automatically generated anywhere a caller provides a master -key provider. The default CMM collects encrypted data keys from all master keys referenced by the master key -provider. +An example of a CMM is the default CMM, +which is automatically generated anywhere a caller provides a keyring. + +Note: You must also install the `AWS Cryptographic Material Providers Library (MPL)`_ +to create and use CMMs that use keyrings. +CMMs that use master key providers have been marked as legacy since v4 of this library. -An example of a more advanced CMM is the caching CMM, which caches cryptographic materials provided by another CMM. +Legacy Concepts +=============== +This section describes legacy concepts introduced in earlier versions of this library. +These components have been superseded by new components in the `AWS Cryptographic Material Providers Library (MPL)`_. +Please avoid using these components, and instead use components in the MPL. Master Key Providers -------------------- Master key providers are resources that provide master keys. -An example of a master key provider is `AWS KMS`_. To encrypt data in this client, a ``MasterKeyProvider`` object must contain at least one ``MasterKey`` object. ``MasterKeyProvider`` objects can also contain other ``MasterKeyProvider`` objects. +NOTE: Master key providers are legacy components +and have been superseded by keyrings +provided by the `AWS Cryptographic Material Providers Library (MPL)`_. +Please install this library and migrate master key providers to keyring interfaces. + Master Keys ----------- Master keys generate, encrypt, and decrypt data keys. -An example of a master key is a `KMS customer master key (CMK)`_. +An example of a master key is an `AWS KMS key`_. -Data Keys ---------- -Data keys are the encryption keys that are used to encrypt your data. If your algorithm suite -uses a key derivation function, the data key is used to generate the key that directly encrypts the data. +NOTE: Master keys are legacy constructs +and have been superseded by keyrings +provided by the `AWS Cryptographic Material Providers Library (MPL)`_. +Please install this library and migrate master key providers to keyring interfaces. ***** Usage @@ -110,147 +145,71 @@ version of the AWS Encryption SDK, we recommend using the default value. ) -You must then create an instance of either a master key provider or a CMM. The examples in this -readme use the ``StrictAwsKmsMasterKeyProvider`` class. +You must then create an instance of either a keyring (with the MPL installed) or a CMM. +Note: You must also install the `AWS Cryptographic Material Providers Library (MPL)`_ to use keyrings. +(You may also provide an instance of a legacy master key provider, but this is not recommended.) + +AwsKmsMultiKeyring +================== -StrictAwsKmsMasterKeyProvider -============================= -A ``StrictAwsKmsMasterKeyProvider`` is configured with an explicit list of AWS KMS -CMKs with which to encrypt and decrypt data. On encryption, it encrypts the plaintext with all -configured CMKs. On decryption, it only attempts to decrypt ciphertexts that have been wrapped -with a CMK that matches one of the configured CMK ARNs. +An ``AwsKmsMultiKeyring`` is configured with a generator keyring and a list of +child keyrings of type ``AwsKmsKeyring``. The effect is like using several keyrings +in a series. When you use a multi-keyring to encrypt data, any of the wrapping keys +in any of its keyrings can decrypt that data. -To create a ``StrictAwsKmsMasterKeyProvider`` you must provide one or more CMKs. For providers that will only -be used for encryption, you can use any valid `KMS key identifier`_. For providers that will be used for decryption, you -must use the key ARN; key ids, alias names, and alias ARNs are not supported. +On encryption, the generator keyring generates and encrypts the plaintext data key. +Then, all of the wrapping keys in all of the child keyrings encrypt the same plaintext data key. +The final `encrypted message`_ will include a copy of the data key encrypted by each configured key. +On decryption, the AWS Encryption SDK uses the keyrings to try to decrypt one of the encrypted data keys. +The keyrings are called in the order that they are specified in the multi-keyring. +Processing stops as soon as any key in any keyring can decrypt an encrypted data key. -Because the ``StrictAwsKmsMasterKeyProvider`` uses the `boto3 SDK`_ to interact with `AWS KMS`_, +An individual ``AwsKmsKeyring`` in an ``AwsKmsMultiKeyring`` is configured with an +AWS KMS key ARN. +For keyrings that will only be used for encryption, +you can use any valid `KMS key identifier`_. +For providers that will be used for decryption, +you must use the key ARN. +Key ids, alias names, and alias ARNs are not supported for decryption. + +Because the ``AwsKmsMultiKeyring`` uses the `boto3 SDK`_ to interact with `AWS KMS`_, it requires AWS Credentials. To provide these credentials, use the `standard means by which boto3 locates credentials`_ or provide a -pre-existing instance of a ``botocore session`` to the ``StrictAwsKmsMasterKeyProvider``. +pre-existing instance of a ``botocore session`` to the ``AwsKmsMultiKeyring``. This latter option can be useful if you have an alternate way to store your AWS credentials or you want to reuse an existing instance of a botocore session in order to decrease startup costs. +You can also add KMS keys from multiple regions to the ``AwsKmsMultiKeyring``. -If you configure the the ``StrictAwsKmsMasterKeyProvider`` with multiple CMKs, the `final message`_ -will include a copy of the data key encrypted by each configured CMK. +See `examples/src/aws_kms_multi_keyring_example.py`_ for a code example configuring and using +a ``AwsKmsMultiKeyring`` with the ``EncryptionSDKClient``. -.. code:: python - - import aws_encryption_sdk - - kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ]) - -You can add CMKs from multiple regions to the ``StrictAwsKmsMasterKeyProvider``. - -.. code:: python - - import aws_encryption_sdk - - kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - 'arn:aws:kms:us-west-2:3333333333333:key/33333333-3333-3333-3333-333333333333', - 'arn:aws:kms:ap-northeast-1:4444444444444:key/44444444-4444-4444-4444-444444444444' - ]) - - -DiscoveryAwsKmsMasterKeyProvider -================================ -We recommend using a ``StrictAwsKmsMasterKeyProvider`` in order to ensure that you can only -encrypt and decrypt data using the AWS KMS CMKs you expect. However, if you are unable to -explicitly identify the AWS KMS CMKs that should be used for decryption, you can instead -use a ``DiscoveryAwsKmsMasterKeyProvider`` for decryption operations. This provider +AwsKmsDiscoveryKeyring +====================== +We recommend using an ``AwsKmsMultiKeyring`` in order to ensure that you can only +encrypt and decrypt data using the AWS KMS key ARN you expect. However, if you are unable to +explicitly identify the AWS KMS key ARNs that should be used for decryption, you can instead +use an ``AwsKmsDiscoveryKeyring`` for decryption operations. This provider attempts decryption of any ciphertexts as long as they match a ``DiscoveryFilter`` that you configure. A ``DiscoveryFilter`` consists of a list of AWS account ids and an AWS partition. +If you do not want to filter the set of allowed accounts, you can also omit the ``discovery_filter`` argument. -.. code:: python +Note that an ``AwsKmsDiscoveryKeyring`` cannot be used for encryption operations. - import aws_encryption_sdk - from aws_encryption_sdk.key_providers.kms import DiscoveryFilter +See `examples/src/aws_kms_discovery_keyring_example.py`_ for a code example configuring and using +an ``AwsKmsDiscoveryKeyring`` with the ``EncryptionSDKClient``. - discovery_filter = DiscoveryFilter( - account_ids=['222222222222', '333333333333'], - partition='aws' - ) - kms_key_provider = aws_encryption_sdk.DiscoveryAwsKmsMasterKeyProvider( - discovery_filter=discovery_filter - ) - -If you do not want to filter the set of allowed accounts, you can also omit the ``discovery_filter`` argument. - -Note that a ``DiscoveryAwsKmsMasterKeyProvider`` cannot be used for encryption operations. Encryption and Decryption ========================= -After you create an instance of an ``EncryptionSDKClient`` and a ``MasterKeyProvider``, you can use either of -the client's two ``encrypt``/``decrypt`` functions to encrypt and decrypt your data. - -.. code:: python - - import aws_encryption_sdk - from aws_encryption_sdk.identifiers import CommitmentPolicy - - client = aws_encryption_sdk.EncryptionSDKClient( - commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT - ) - - kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ]) - my_plaintext = b'This is some super secret data! Yup, sure is!' - - my_ciphertext, encryptor_header = client.encrypt( - source=my_plaintext, - key_provider=kms_key_provider - ) - - decrypted_plaintext, decryptor_header = client.decrypt( - source=my_ciphertext, - key_provider=kms_key_provider - ) - - assert my_plaintext == decrypted_plaintext - assert encryptor_header.encryption_context == decryptor_header.encryption_context - -You can provide an `encryption context`_: a form of additional authenticating information. - -.. code:: python - - import aws_encryption_sdk - from aws_encryption_sdk.identifiers import CommitmentPolicy - - client = aws_encryption_sdk.EncryptionSDKClient( - commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT - ) +After you create an instance of an ``EncryptionSDKClient`` and a ``Keyring``, you can use +the client's ``encrypt`` and ``decrypt`` functions to encrypt and decrypt your data. - kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ]) - my_plaintext = b'This is some super secret data! Yup, sure is!' - - my_ciphertext, encryptor_header = client.encrypt( - source=my_plaintext, - key_provider=kms_key_provider, - encryption_context={ - 'not really': 'a secret', - 'but adds': 'some authentication' - } - ) - - decrypted_plaintext, decryptor_header = client.decrypt( - source=my_ciphertext, - key_provider=kms_key_provider - ) - - assert my_plaintext == decrypted_plaintext - assert encryptor_header.encryption_context == decryptor_header.encryption_context +You can also provide an `encryption context`_: a form of additional authenticating information. +See code in the `examples/src/`_ directory for code examples configuring and using +keyrings and encryption context with the ``EncryptionSDKClient``. Streaming ========= @@ -259,57 +218,19 @@ memory at once, you can use this library's streaming clients directly. The strea file-like objects, and behave exactly as you would expect a Python file object to behave, offering context manager and iteration support. -.. code:: python - - import aws_encryption_sdk - from aws_encryption_sdk.identifiers import CommitmentPolicy - import filecmp - - client = aws_encryption_sdk.EncryptionSDKClient( - commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT - ) - - kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ]) - plaintext_filename = 'my-secret-data.dat' - ciphertext_filename = 'my-encrypted-data.ct' - - with open(plaintext_filename, 'rb') as pt_file, open(ciphertext_filename, 'wb') as ct_file: - with client.stream( - mode='e', - source=pt_file, - key_provider=kms_key_provider - ) as encryptor: - for chunk in encryptor: - ct_file.write(chunk) - - new_plaintext_filename = 'my-decrypted-data.dat' - - with open(ciphertext_filename, 'rb') as ct_file, open(new_plaintext_filename, 'wb') as pt_file: - with client.stream( - mode='d', - source=ct_file, - key_provider=kms_key_provider - ) as decryptor: - for chunk in decryptor: - pt_file.write(chunk) - - assert filecmp.cmp(plaintext_filename, new_plaintext_filename) - assert encryptor.header.encryption_context == decryptor.header.encryption_context +See `examples/src/file_streaming_example.py`_ for a code example streaming data to and from files. Performance Considerations ========================== Adjusting the frame size can significantly improve the performance of encrypt/decrypt operations with this library. -Processing each frame in a framed message involves a certain amount of overhead. If you are encrypting a large file, -increasing the frame size can offer potentially significant performance gains. We recommend that you tune these values +Processing each frame in a framed message involves a certain amount of overhead. If you are encrypting a large file, +increasing the frame size can offer potentially significant performance gains. We recommend that you tune these values to your use-case in order to obtain peak performance. Thread safety ========================== -The ``EncryptionSDKClient`` and all provided ``CryptoMaterialsManager`` are thread safe. +The ``EncryptionSDKClient`` and all provided ``CryptoMaterialsManager`` in this library are thread safe. But instances of ``BaseKMSMasterKeyProvider`` MUST not be shared between threads, for the reasons outlined in `the boto3 docs `_. @@ -323,17 +244,28 @@ Finally, while the ``CryptoMaterialsCache`` is thread safe, sharing entries in that cache across threads needs to be done carefully (see the !Note about partition name `in the API Docs `_). +**Important:** Components from the `AWS Cryptographic Material Providers Library (MPL)`_ +have separate thread safety considerations. +For more information, see the note on thread safety in that project's README (TODO-MPL: link) + + .. _AWS Encryption SDK: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html .. _cryptography: https://cryptography.io/en/latest/ .. _cryptography installation guide: https://cryptography.io/en/latest/installation/ .. _Read the Docs: http://aws-encryption-sdk-python.readthedocs.io/en/latest/ .. _GitHub: https://github.com/aws/aws-encryption-sdk-python/ .. _AWS KMS: https://docs.aws.amazon.com/kms/latest/developerguide/overview.html -.. _KMS customer master key (CMK): https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys +.. _AWS KMS key: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys .. _KMS key identifier: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id .. _boto3 SDK: https://boto3.readthedocs.io/en/latest/ .. _standard means by which boto3 locates credentials: https://boto3.readthedocs.io/en/latest/guide/configuration.html -.. _final message: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html +.. _encrypted message: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html .. _encryption context: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context .. _Security issue notifications: ./CONTRIBUTING.md#security-issue-notifications .. _Support Policy: ./SUPPORT_POLICY.rst +.. _AWS Cryptographic Material Providers Library (MPL): https://github.com/aws/aws-cryptographic-material-providers-library +.. _AWS Documentation for Keyrings: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html +.. _examples/src/aws_kms_multi_keyring_example.py: https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/aws_kms_multi_keyring_example.py +.. _examples/src/aws_kms_discovery_keyring_example.py: https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/aws_kms_discovery_keyring_example.py +.. _examples/src/: https://github.com/aws/aws-encryption-sdk-python/tree/master/examples/src/ +.. _examples/src/file_streaming_example.py: https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/file_streaming_example.py diff --git a/src/aws_encryption_sdk/__init__.py b/src/aws_encryption_sdk/__init__.py index 21d3084a1..9f3525349 100644 --- a/src/aws_encryption_sdk/__init__.py +++ b/src/aws_encryption_sdk/__init__.py @@ -35,7 +35,8 @@ class EncryptionSDKClientConfig(object): :param commitment_policy: The commitment policy to apply to encryption and decryption requests :type commitment_policy: aws_encryption_sdk.materials_manager.identifiers.CommitmentPolicy - :param max_encrypted_data_keys: The maximum number of encrypted data keys to allow during encryption and decryption + :param max_encrypted_data_keys: The maximum number of encrypted data keys to allow during + encryption and decryption :type max_encrypted_data_keys: None or positive int """ @@ -94,15 +95,26 @@ def encrypt(self, **kwargs): .. code:: python + >>> import boto3 + >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() - >>> kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - ... 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - ... 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ... ]) + >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + ... config=MaterialProvidersConfig() + ... ) + >>> keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + ... kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', + ... kms_client=boto3.client('kms', region_name="us-west-2") + ... ) + >>> kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + ... input=keyring_input + ... ) >>> my_ciphertext, encryptor_header = client.encrypt( ... source=my_plaintext, - ... key_provider=kms_key_provider + ... keyring=kms_keyring ... ) :param config: Client configuration object (config or individual parameters required) @@ -110,11 +122,14 @@ def encrypt(self, **kwargs): :param source: Source data to encrypt or decrypt :type source: str, bytes, io.IOBase, or file :param materials_manager: `CryptoMaterialsManager` that returns cryptographic materials - (requires either `materials_manager` or `key_provider`) + (requires either `materials_manager` or `keyring`) :type materials_manager: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager :param key_provider: `MasterKeyProvider` that returns data keys for encryption (requires either `materials_manager` or `key_provider`) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` that returns keyring for encryption + (requires either `materials_manager` or `keyring`) + :type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -124,7 +139,7 @@ def encrypt(self, **kwargs): .. note:: If `source_length` and `materials_manager` are both provided, the total plaintext bytes encrypted will not be allowed to exceed `source_length`. To maintain backwards compatibility, - this is not enforced if a `key_provider` is provided. + this is not enforced if a `keyring` is provided. :param dict encryption_context: Dictionary defining encryption context :param algorithm: Algorithm to use for encryption @@ -148,15 +163,26 @@ def decrypt(self, **kwargs): .. code:: python + >>> import boto3 + >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() - >>> kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - ... 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - ... 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ... ]) + >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + ... config=MaterialProvidersConfig() + ... ) + >>> keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + ... kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', + ... kms_client=boto3.client('kms', region_name="us-west-2") + ... ) + >>> kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + ... input=keyring_input + ... ) >>> my_plaintext, decryptor_header = client.decrypt( ... source=my_ciphertext, - ... key_provider=kms_key_provider + ... keyring=kms_keyring ... ) :param config: Client configuration object (config or individual parameters required) @@ -164,11 +190,14 @@ def decrypt(self, **kwargs): :param source: Source data to encrypt or decrypt :type source: str, bytes, io.IOBase, or file :param materials_manager: `CryptoMaterialsManager` that returns cryptographic materials - (requires either `materials_manager` or `key_provider`) + (requires either `materials_manager` or `keyring`) :type materials_manager: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager :param key_provider: `MasterKeyProvider` that returns data keys for decryption (requires either `materials_manager` or `key_provider`) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param keyring: `IKeyring` that returns keyring for encryption + (requires either `materials_manager` or `keyring`) + :type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -208,28 +237,39 @@ def stream(self, **kwargs): .. code:: python + >>> import boto3 + >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() - >>> kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - ... 'arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', - ... 'arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333' - ... ]) + >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + ... config=MaterialProvidersConfig() + ... ) + >>> keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + ... kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222', + ... kms_client=boto3.client('kms', region_name="us-west-2") + ... ) + >>> kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + ... input=keyring_input + ... ) >>> plaintext_filename = 'my-secret-data.dat' >>> ciphertext_filename = 'my-encrypted-data.ct' >>> with open(plaintext_filename, 'rb') as pt_file, open(ciphertext_filename, 'wb') as ct_file: - ... with client.stream( + ... with client.stream( ... mode='e', ... source=pt_file, - ... key_provider=kms_key_provider + ... keyring=kms_keyring ... ) as encryptor: ... for chunk in encryptor: - ... ct_file.write(chunk) - >>> new_plaintext_filename = 'my-decrypted-data.dat' - >>> with open(ciphertext_filename, 'rb') as ct_file, open(new_plaintext_filename, 'wb') as pt_file: + ... ct_file.write(chunk) + >>> decrypted_filename = 'my-decrypted-data.dat' + >>> with open(ciphertext_filename, 'rb') as ct_file, open(decrypted_filename, 'wb') as pt_file: ... with client.stream( ... mode='d', ... source=ct_file, - ... key_provider=kms_key_provider + ... keyring=kms_keyring ... ) as decryptor: ... for chunk in decryptor: ... pt_file.write(chunk) diff --git a/src/aws_encryption_sdk/internal/deprecation.py b/src/aws_encryption_sdk/internal/deprecation.py new file mode 100644 index 000000000..18e587237 --- /dev/null +++ b/src/aws_encryption_sdk/internal/deprecation.py @@ -0,0 +1,32 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Module containing utilities for deprecated components.""" +import functools +import warnings + + +def deprecated(reason): + """Decorator to apply to classes to emit deprecation warnings.""" + def decorator(cls): + # If class does not define init, + # its default init it Python's object.__init__, + # which does nothing, but cannot be wrapped. + if cls.__init__ is object.__init__: + # Make a new init that just emits this deprecation warning. + def new_init(self, *args, **kwargs): # pylint: disable=unused-argument + warnings.warn(f"{cls.__name__} is deprecated: {reason}", + category=DeprecationWarning, stacklevel=2) + else: + original_init = cls.__init__ + + # Wrap the original init method with a deprecation warning. + @functools.wraps(cls.__init__) + def new_init(self, *args, **kwargs): + warnings.warn(f"{cls.__name__} is deprecated: {reason}", + category=DeprecationWarning, stacklevel=2) + original_init(self, *args, **kwargs) + + cls.__init__ = new_init + return cls + + return decorator From ca7e15905ab83ca39b7a097fe68675d11f996f4e Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 5 Aug 2024 12:24:30 -0700 Subject: [PATCH 18/51] chore: Change MPL branch, remove PYTHONPATH workarounds (#683) --- .github/workflows/ci_tests.yaml | 6 +----- examples/src/aws_kms_discovery_keyring_example.py | 6 ------ .../aws_kms_discovery_multi_keyring_example.py | 6 ------ examples/src/aws_kms_keyring_example.py | 6 ------ .../src/aws_kms_mrk_discovery_keyring_example.py | 6 ------ ...aws_kms_mrk_discovery_multi_keyring_example.py | 6 ------ examples/src/aws_kms_mrk_keyring_example.py | 6 ------ examples/src/aws_kms_mrk_multi_keyring_example.py | 6 ------ examples/src/aws_kms_multi_keyring_example.py | 6 ------ examples/src/aws_kms_rsa_keyring_example.py | 6 ------ examples/src/branch_key_id_supplier_example.py | 8 ++++---- ...ult_cryptographic_materials_manager_example.py | 7 ------- examples/src/file_streaming_example.py | 6 ------ examples/src/hierarchical_keyring_example.py | 6 ------ examples/src/legacy/module_.py | 1 - .../migration_set_commitment_policy_example.py | 6 ------ examples/src/module_.py | 1 - examples/src/multi_keyring_example.py | 6 ------ examples/src/raw_aes_keyring_example.py | 6 ------ examples/src/raw_rsa_keyring_example.py | 6 ------ examples/src/required_encryption_context_cmm.py | 6 ------ .../src/set_encryption_algorithm_suite_example.py | 6 ------ performance_tests/requirements_mpl.txt | 2 +- requirements_mpl.txt | 2 +- setup.py | 2 +- test_vector_handlers/requirements_mpl.txt | 2 +- .../manifests/full_message/decrypt.py | 15 ++++++++++++++- .../awses_test_vectors/manifests/mpl_keyring.py | 2 +- 28 files changed, 24 insertions(+), 126 deletions(-) delete mode 100644 examples/src/legacy/module_.py delete mode 100644 examples/src/module_.py diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index 7ec273ba2..1a3229683 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -25,11 +25,7 @@ jobs: matrix: os: - ubuntu-latest - # Windows fails due to "No module named 'Wrappers'" - # This SHOULD be fixed once Dafny generates fully-qualified import statements - # (i.e. doo files, per-package module names) - # Disable for now - # - windows-latest + - windows-latest - macos-12 python: - 3.8 diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index 4695e8783..d78121bc3 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -32,7 +32,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -49,11 +48,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 60d74ff31..9381a740b 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -29,7 +29,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -45,11 +44,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index b166aab99..8977e3750 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -17,7 +17,6 @@ For more information on how to use KMS keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -29,11 +28,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index 8ba80b621..23d6cb322 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -34,7 +34,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -50,11 +49,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index 47cb80f1d..adb249e2a 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -36,7 +36,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -52,11 +51,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index 65d8be71b..edb3cc410 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -21,7 +21,6 @@ For more info on KMS MRK (multi-region keys), see the KMS documentation: https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -33,11 +32,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 9c87008fe..6b1e64eec 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -27,7 +27,6 @@ For more info on KMS MRK (multi-region keys), see the KMS documentation: https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -39,11 +38,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index 715181646..7cba36167 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -36,7 +36,6 @@ For more information on how to use Multi keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -48,11 +47,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index 337dd14b6..fd05fc20b 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -14,7 +14,6 @@ # For more information on how to use KMS keyrings, see # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -27,11 +26,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/branch_key_id_supplier_example.py b/examples/src/branch_key_id_supplier_example.py index b3d26497b..b25d9abeb 100644 --- a/examples/src/branch_key_id_supplier_example.py +++ b/examples/src/branch_key_id_supplier_example.py @@ -25,15 +25,15 @@ def get_branch_key_id( """Returns branch key ID from the tenant ID in input's encryption context.""" encryption_context: Dict[str, str] = param.encryption_context - if b"tenant" not in encryption_context: + if "tenant" not in encryption_context: raise ValueError("EncryptionContext invalid, does not contain expected tenant key value pair.") - tenant_key_id: str = encryption_context.get(b"tenant") + tenant_key_id: str = encryption_context.get("tenant") branch_key_id: str - if tenant_key_id == b"TenantA": + if tenant_key_id == "TenantA": branch_key_id = self.branch_key_id_for_tenant_A - elif tenant_key_id == b"TenantB": + elif tenant_key_id == "TenantB": branch_key_id = self.branch_key_id_for_tenant_B else: raise ValueError(f"Item does not contain valid tenant ID: {tenant_key_id=}") diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py index bfffc36d9..15a9f22cf 100644 --- a/examples/src/default_cryptographic_materials_manager_example.py +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -18,8 +18,6 @@ For more information on Cryptographic Material Managers, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager """ -import sys - import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -33,11 +31,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index 72decde60..3f547d220 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -25,7 +25,6 @@ """ import filecmp import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -36,11 +35,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - def encrypt_and_decrypt_with_keyring( plaintext_filename: str, diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index c781f4f40..00dadf9d8 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -31,7 +31,6 @@ This example also requires using a KMS Key. You need the following access on this key: - GenerateDataKeyWithoutPlaintext - Decrypt """ -import sys import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example @@ -55,11 +54,6 @@ from .branch_key_id_supplier_example import ExampleBranchKeyIdSupplier -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -module_root_dir = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(module_root_dir) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/legacy/module_.py b/examples/src/legacy/module_.py deleted file mode 100644 index 3e8d3062a..000000000 --- a/examples/src/legacy/module_.py +++ /dev/null @@ -1 +0,0 @@ -"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 4bd0bc372..3851df0e2 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -20,7 +20,6 @@ For more information on setting your commitment policy, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#commitment-policy """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -32,11 +31,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/module_.py b/examples/src/module_.py deleted file mode 100644 index 3e8d3062a..000000000 --- a/examples/src/module_.py +++ /dev/null @@ -1 +0,0 @@ -"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index b12ab61a3..20af7ba81 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -37,7 +37,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html """ import secrets -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders @@ -54,11 +53,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index d8634f774..ab9603af6 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -23,7 +23,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html """ import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -34,11 +33,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 4a38fd166..1200a7c72 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -33,7 +33,6 @@ For more information on how to use Raw RSA keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html """ -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -48,11 +47,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/required_encryption_context_cmm.py b/examples/src/required_encryption_context_cmm.py index 1d5140e6d..edbb3f414 100644 --- a/examples/src/required_encryption_context_cmm.py +++ b/examples/src/required_encryption_context_cmm.py @@ -6,7 +6,6 @@ on encrypt such that they will not be stored on the message, but WILL be included in the header signature. On decrypt, the client MUST supply the key/value pair(s) that were not stored to successfully decrypt the message. """ -import sys import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example @@ -25,11 +24,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks -module_root_dir = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(module_root_dir) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index 200570083..75eaee85a 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -39,7 +39,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html """ import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -51,11 +50,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index 209e10f2c..28d7dc356 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 209e10f2c..28d7dc356 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/setup.py b/setup.py index 8ed2fe4e0..c069bade1 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ def get_requirements(): extras_require={ "MPL": ["aws-cryptographic-material-providers @" \ "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ - "lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + "lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], }, classifiers=[ "Development Status :: 5 - Production/Stable", diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt index c7927a851..1aab5f534 100644 --- a/test_vector_handlers/requirements_mpl.txt +++ b/test_vector_handlers/requirements_mpl.txt @@ -1 +1 @@ -amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index 8c500caba..c2a233ca6 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -8,6 +8,8 @@ import json import os from enum import Enum +import contextlib +import io import attr import aws_encryption_sdk @@ -126,8 +128,19 @@ def match(self, name, decrypt_fn): # The ESDK implementations are not consistent in the types of errors they produce # or the exact error messages they use. The most important thing to test is that decryption # fails in some way, and hence the overly-broad implicit try/catch here. + with pytest.raises(Exception): - decrypt_fn() + # Here, an exception is expected. + # However, when the expected exception is raised, + # the Python environment will write stderrs to console. + # Redirect stderr to null-like sink + # so local and CI build logs are cleaner, + # and any actual issues are easier to see. + # If an exception is not raised as expected, + # `pytest.raises` will fail. + tmp_file = io.StringIO() + with contextlib.redirect_stderr(tmp_file): + decrypt_fn() except BaseException: # Translate the exception just to attach context. raise RuntimeError( diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py index ec35147c0..566bd7f55 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -31,7 +31,7 @@ from aws_cryptographic_materialproviders.mpl.models import CreateMultiKeyringInput import _dafny -import UTF8 +from standard_library.internaldafny.generated import UTF8 # Ignore pylint not being able to read a module that requires the MPL # pylint: disable=no-name-in-module From 0de58cd6463affd5f942be05baa6e505beaa662d Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 7 Aug 2024 13:38:55 -0700 Subject: [PATCH 19/51] feat(test_vector_handlers): Hierarchy keyring test vectors (#674) --- buildspec.yml | 23 ++++++- .../py312/decrypt_hkeyring_with_keyrings.yml | 32 ++++++++++ .../py312/decrypt_hkeyring_with_masterkey.yml | 31 ++++++++++ codebuild/py312/decrypt_hkeyring_with_net.yml | 50 +++++++++++++++ .../generate_hkeyring_decrypt_vectors.yml | 33 ++++++++++ .../manifests/full_message/decrypt.py | 17 ++++- .../full_message/decrypt_generation.py | 25 +++++++- .../manifests/full_message/encrypt.py | 21 +++++++ .../src/awses_test_vectors/manifests/keys.py | 62 ++++++++++++++++++- .../manifests/master_key.py | 14 ++++- .../manifests/mpl_keyring.py | 38 +++++++++++- 11 files changed, 334 insertions(+), 12 deletions(-) create mode 100644 codebuild/py312/decrypt_hkeyring_with_keyrings.yml create mode 100644 codebuild/py312/decrypt_hkeyring_with_masterkey.yml create mode 100644 codebuild/py312/decrypt_hkeyring_with_net.yml create mode 100644 codebuild/py312/generate_hkeyring_decrypt_vectors.yml diff --git a/buildspec.yml b/buildspec.yml index 583fae56f..4665ac89e 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -296,7 +296,28 @@ batch: buildspec: codebuild/py312/decrypt_keyrings_with_js.yml env: image: aws/codebuild/standard:7.0 - + - identifier: py312_generate_hkeyring_decrypt_vectors + buildspec: codebuild/py312/generate_hkeyring_decrypt_vectors.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_hkeyring_with_masterkey + depend-on: + - py312_generate_hkeyring_decrypt_vectors + buildspec: codebuild/py312/decrypt_hkeyring_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_hkeyring_with_keyrings + depend-on: + - py312_generate_hkeyring_decrypt_vectors + buildspec: codebuild/py312/decrypt_hkeyring_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_hkeyring_with_net + depend-on: + - py312_generate_hkeyring_decrypt_vectors + buildspec: codebuild/py312/decrypt_hkeyring_with_net.yml + env: + image: aws/codebuild/standard:7.0 - identifier: code_coverage buildspec: codebuild/coverage/coverage.yml diff --git a/codebuild/py312/decrypt_hkeyring_with_keyrings.yml b/codebuild/py312/decrypt_hkeyring_with_keyrings.yml new file mode 100644 index 000000000..5bcd26738 --- /dev/null +++ b/codebuild/py312/decrypt_hkeyring_with_keyrings.yml @@ -0,0 +1,32 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + # This manifest has coverage for both HKeyring and required encryption context CMM + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest.zip + - unzip 312_hkeyring_reccmm_manifest.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_hkeyring_reccmm_manifest/manifest.json \ + --keyrings \ No newline at end of file diff --git a/codebuild/py312/decrypt_hkeyring_with_masterkey.yml b/codebuild/py312/decrypt_hkeyring_with_masterkey.yml new file mode 100644 index 000000000..be67235d7 --- /dev/null +++ b/codebuild/py312/decrypt_hkeyring_with_masterkey.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + # This manifest has coverage for both HKeyring and required encryption context CMM + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest.zip + - unzip 312_hkeyring_reccmm_manifest.zip + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../312_hkeyring_reccmm_manifest/manifest.json diff --git a/codebuild/py312/decrypt_hkeyring_with_net.yml b/codebuild/py312/decrypt_hkeyring_with_net.yml new file mode 100644 index 000000000..6a3b321eb --- /dev/null +++ b/codebuild/py312/decrypt_hkeyring_with_net.yml @@ -0,0 +1,50 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download previously generated vectors + # This manifest has coverage for both HKeyring and required encryption context CMM + - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest.zip + - unzip 312_hkeyring_reccmm_manifest.zip + - export DAFNY_AWS_ESDK_TEST_VECTOR_MANIFEST_PATH="${PWD}/312_hkeyring_reccmm_manifest/manifest.json" + + # Download dafny + - curl https://github.com/dafny-lang/dafny/releases/download/v4.7.0/dafny-4.7.0-x64-ubuntu-20.04.zip -L -o dafny.zip + - unzip -qq dafny.zip && rm dafny.zip + - export PATH="$PWD/dafny:$PATH" + + # Clone SDK-Dafny repo to get test vectors runner + - git clone --recurse-submodules https://github.com/aws/aws-encryption-sdk-dafny.git + # TODO: Change branch to published when available + - cd aws-encryption-sdk-dafny + - git checkout lucmcdon/hkeyring-vectors + - git pull + - cd AwsEncryptionSDK/ + - make transpile_net + - cd ../mpl/TestVectorsAwsCryptographicMaterialProviders/ + - make transpile_net + + # Change TestVectors to reference the published .NET ESDK + - cd ../../AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors + # - sed -i -e 's///g' AWSEncryptionSDKTestVectorLib.csproj + # - cd ../TestVectors + + build: + commands: + - dotnet test --framework net6.0 \ No newline at end of file diff --git a/codebuild/py312/generate_hkeyring_decrypt_vectors.yml b/codebuild/py312/generate_hkeyring_decrypt_vectors.yml new file mode 100644 index 000000000..b0a755360 --- /dev/null +++ b/codebuild/py312/generate_hkeyring_decrypt_vectors.yml @@ -0,0 +1,33 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt_generate-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers/test/aws-crypto-tools-test-vector-framework + # Checkout WIP branch with manifest containing HKeyring and required EC CMM test cases + - git checkout lucmcdon/hierarchy-test-vectors + - git pull + - cd ../.. + - | + tox -- \ + --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0007-hkeyring-reccmm-generate-manifest.json \ + --output 312_hkeyring_reccmm_manifest \ + --keyrings + - zip -r 312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest + - aws s3 cp 312_hkeyring_reccmm_manifest.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index c2a233ca6..79df4f2cf 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -225,7 +225,7 @@ class MessageDecryptionTestScenario(object): master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) result = attr.ib(validator=attr.validators.instance_of(MessageDecryptionTestResult)) keyrings = attr.ib(validator=attr.validators.instance_of(bool)) - cmm_type = attr.ib(validator=attr.validators.instance_of(str)) + cmm_type = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str))) decryption_method = attr.ib( default=None, validator=attr.validators.optional(attr.validators.instance_of(DecryptionMethod)) ) @@ -292,6 +292,7 @@ def from_scenario( else: master_key_specs = [ MasterKeySpec.from_scenario(spec) for spec in raw_master_key_specs + if spec["type"] != "aws-kms-hierarchy" ] def master_key_provider_fn(): @@ -310,7 +311,8 @@ def master_key_provider_fn(): encryption_context = {} # MPL test vectors add CMM types to the test vectors manifests - if "cmm" in scenario: + if "cmm" in scenario \ + and scenario["cmm"] is not None: if scenario["cmm"] == "Default": # Master keys and keyrings can handle default CMM cmm_type = scenario["cmm"] @@ -323,11 +325,17 @@ def master_key_provider_fn(): else: return None else: - raise ValueError("Unrecognized cmm_type: " + cmm_type) + raise ValueError("Unrecognized cmm_type: " + scenario["cmm"]) else: # If unspecified, set "Default" as the default cmm_type = "Default" + # If this scenario does not have any key providers, + # do not create a scenario. + # Caller logic should expect `None` to mean "no scenario". + if master_key_provider_fn() is None: + return None + return cls( ciphertext_uri=scenario["ciphertext"], ciphertext=ciphertext_reader(scenario["ciphertext"]), @@ -358,6 +366,9 @@ def scenario_spec(self): spec["decryption-method"] = self.decryption_method.value if self.description is not None: spec["description"] = self.description + spec["cmm"] = self.cmm_type + spec["encryption-context"] = self.encryption_context + return spec def _one_shot_decrypt(self): diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py index 93510d891..63f8b8ff3 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py @@ -81,7 +81,7 @@ # We only actually need these imports when running the mypy checks pass -SUPPORTED_VERSIONS = (2,) +SUPPORTED_VERSIONS = (2, 4, ) class TamperingMethod: @@ -410,6 +410,8 @@ class MessageDecryptionTestScenarioGenerator(object): decryption_master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) result = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(MessageDecryptionTestResult))) keyrings = attr.ib(validator=attr.validators.instance_of(bool)) + cmm_type = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str))) + encryption_context = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(dict))) @classmethod def from_scenario(cls, scenario, keys, plaintexts, keyrings, keys_uri): @@ -432,6 +434,10 @@ def from_scenario(cls, scenario, keys, plaintexts, keyrings, keys_uri): keyrings, keys_uri, ) + + if encryption_scenario is None: + return None + tampering = scenario.get("tampering") tampering_method = TamperingMethod.from_tampering_spec(tampering) decryption_method_spec = scenario.get("decryption-method") @@ -457,6 +463,16 @@ def decryption_master_key_provider_fn(): result_spec = scenario.get("result") result = MessageDecryptionTestResult.from_result_spec(result_spec, None) if result_spec else None + try: + encryption_context = encryption_scenario_spec["encryption-context"] + except KeyError: + encryption_context = None + + try: + cmm_type = encryption_scenario_spec["cmm"] + except KeyError: + cmm_type = None + return cls( encryption_scenario=encryption_scenario, tampering_method=tampering_method, @@ -465,6 +481,8 @@ def decryption_master_key_provider_fn(): decryption_master_key_provider_fn=decryption_master_key_provider_fn, result=result, keyrings=keyrings, + cmm_type=cmm_type, + encryption_context=encryption_context, ) def run(self, ciphertext_writer, plaintext_uri): @@ -494,8 +512,8 @@ def decryption_test_scenario_pair(self, ciphertext_writer, ciphertext_to_decrypt decryption_method=self.decryption_method, result=expected_result, keyrings=self.keyrings, - cmm_type="Default", - encryption_context={} + cmm_type=self.cmm_type, + encryption_context=self.encryption_context, ), ) @@ -533,6 +551,7 @@ def _generate_plaintexts(plaintexts_specs): @classmethod def from_file(cls, input_file, keyrings): + # pylint: disable=too-many-locals # type: (IO) -> MessageDecryptionGenerationManifest """Load from a file containing a full message encrypt manifest. diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py index 82c1740de..81581fa8e 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py @@ -83,6 +83,7 @@ class MessageEncryptionTestScenario(object): master_key_specs = attr.ib(validator=iterable_validator(list, MasterKeySpec)) master_key_provider_fn = attr.ib(validator=attr.validators.is_callable()) keyrings = attr.ib(validator=attr.validators.instance_of(bool)) + cmm = attr.ib(validator=attr.validators.instance_of(str)) @classmethod def from_scenario(cls, scenario, keys, plaintexts, keyrings, keys_uri): @@ -114,6 +115,25 @@ def master_key_provider_fn(): return keyring_from_master_key_specs(keys_uri, master_key_specs, "encrypt") return master_key_provider_from_master_key_specs(keys, master_key_specs) + # MPL test vectors add CMM types to the test vectors manifests + if "cmm" in scenario: + if scenario["cmm"] == "Default": + # Master keys and keyrings can handle default CMM + cmm_type = scenario["cmm"] + elif scenario["cmm"] == "RequiredEncryptionContext": + # Skip RequiredEncryptionContext CMM for master keys; + # RequiredEncryptionContext is unsupported for master keys. + # Caller logic should expect `None` to mean "no scenario". + if keyrings: + cmm_type = scenario["cmm"] + else: + return None + else: + raise ValueError("Unrecognized cmm_type: " + cmm_type) + else: + # If unspecified, set "Default" as the default + cmm_type = "Default" + return cls( plaintext_name=scenario["plaintext"], plaintext=plaintexts[scenario["plaintext"]], @@ -123,6 +143,7 @@ def master_key_provider_fn(): master_key_specs=master_key_specs, master_key_provider_fn=master_key_provider_fn, keyrings=keyrings, + cmm=cmm_type, ) def run(self, materials_manager=None): diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/keys.py b/test_vector_handlers/src/awses_test_vectors/manifests/keys.py index 7c55a1617..ce8bf756f 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/keys.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/keys.py @@ -19,6 +19,7 @@ from awses_test_vectors.internal.mypy_types import ( # noqa pylint: disable=unused-import AWS_KMS_KEY_SPEC, + AWS_KMS_HIERARCHY_KEY_SPEC, KEY_SPEC, KEYS_MANIFEST, MANIFEST_VERSION, @@ -100,6 +101,51 @@ def manifest_spec(self): } +@attr.s(init=False) +class AwsKmsHierarchyKeySpec(KeySpec): + """AWS KMS hierarchy key specification. + + :param bool encrypt: Key can be used to encrypt + :param bool decrypt: Key can be used to decrypt + :param str type_name: Master key type name (must be "static-branch-key") + :param str key_id: Branch key ID + """ + + # pylint: disable=too-few-public-methods + + type_name = attr.ib(validator=membership_validator(("static-branch-key",))) + + # noqa pylint: disable=line-too-long,too-many-arguments + def __init__(self, encrypt, decrypt, type_name, key_id, branch_key_version, branch_key, beacon_key): # noqa=D107 + # type: (bool, bool, str, str) -> None + # Workaround pending resolution of attrs/mypy interaction. + # https://github.com/python/mypy/issues/2088 + # https://github.com/python-attrs/attrs/issues/215 + self.type_name = type_name + self.branch_key_version = branch_key_version + self.branch_key = branch_key + self.beacon_key = beacon_key + super(AwsKmsHierarchyKeySpec, self).__init__(encrypt, decrypt, key_id) + + @property + def manifest_spec(self): + # type: () -> AWS_KMS_HIERARCHY_KEY_SPEC + """Build a key specification describing this key specification. + + :return: Key specification JSON + :rtype: dict + """ + return { + "encrypt": self.encrypt, + "decrypt": self.decrypt, + "type": self.type_name, + "key-id": self.key_id, + "branchKeyVersion": self.branch_key_version, + "branchKey": self.branch_key, + "beaconKey": self.beacon_key, + } + + @attr.s(init=False) class ManualKeySpec(KeySpec): # pylint: disable=too-many-arguments @@ -196,8 +242,22 @@ def key_from_manifest_spec(key_spec): key_id = key_spec["key-id"] # type: str return AwsKmsKeySpec(encrypt=encrypt, decrypt=decrypt, type_name=type_name, key_id=key_id) - algorithm = key_spec["algorithm"] # type: str + if key_spec["type"] == "static-branch-key": + branch_key_version = key_spec["branchKeyVersion"] # type: str + branch_key = key_spec["branchKey"] # type: str + beacon_key = key_spec["beaconKey"] # type: str + return AwsKmsHierarchyKeySpec( + encrypt=encrypt, + decrypt=decrypt, + type_name=type_name, + key_id=key_id, + branch_key_version=branch_key_version, + branch_key=branch_key, + beacon_key=beacon_key, + ) + bits = key_spec["bits"] # type: int + algorithm = key_spec["algorithm"] encoding = key_spec["encoding"] # type: str material = key_spec["material"] # type: str return ManualKeySpec( diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index 49b517eae..7e64f9983 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -34,7 +34,7 @@ # We only actually need these imports when running the mypy checks pass -KNOWN_TYPES = ("aws-kms", "aws-kms-mrk-aware", "aws-kms-mrk-aware-discovery", "raw") +KNOWN_TYPES = ("aws-kms", "aws-kms-mrk-aware", "aws-kms-mrk-aware-discovery", "raw", ) KNOWN_ALGORITHMS = ("aes", "rsa") KNOWN_PADDING = ("pkcs1", "oaep-mgf1") KNOWN_PADDING_HASH = ("sha1", "sha256", "sha384", "sha512") @@ -301,7 +301,17 @@ def master_key_provider_from_master_key_specs(keys, master_key_specs): :return: Master key provider combining all loaded master keys :rtype: MasterKeyProvider """ - master_keys = [spec.master_key(keys) for spec in master_key_specs] + master_keys = [] + for spec in master_key_specs: + try: + master_keys.append(spec.master_key(keys)) + # If spec is not a valid master key + # (e.g. hierarchical keyring) + # do not make a master key + except KeyError: + pass + if len(master_keys) == 0: + return None primary = master_keys[0] others = master_keys[1:] for master_key in others: diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py index 566bd7f55..dbabeb3c7 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -36,10 +36,20 @@ # Ignore pylint not being able to read a module that requires the MPL # pylint: disable=no-name-in-module from awses_test_vectors.internal.mpl.keyvectors_provider import KeyVectorsProvider +from awses_test_vectors.internal.util import membership_validator from awses_test_vectors.manifests.keys import KeysManifest # noqa: disable=F401 +from .master_key import KNOWN_TYPES as MASTER_KEY_KNOWN_TYPES, MasterKeySpec -from .master_key import MasterKeySpec +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import + + from awses_test_vectors.internal.mypy_types import MASTER_KEY_SPEC # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + +KEYRING_ONLY_KNOWN_TYPES = ("aws-kms-hierarchy", ) @attr.s @@ -56,6 +66,30 @@ class KeyringSpec(MasterKeySpec): # pylint: disable=too-many-instance-attribute :param str padding_hash: Wrapping key padding hash (required for raw master keys) """ + type_name = attr.ib(validator=membership_validator( + set(MASTER_KEY_KNOWN_TYPES).union(set(KEYRING_ONLY_KNOWN_TYPES)) + )) + + @classmethod + def from_scenario(cls, spec): + # type: (MASTER_KEY_SPEC) -> KeyringSpec + """Load from a keyring specification. + + :param dict spec: Master key specification JSON + :return: Loaded master key specification + :rtype: MasterKeySpec + """ + return cls( + type_name=spec["type"], + key_name=spec.get("key"), + default_mrk_region=spec.get("default-mrk-region"), + discovery_filter=cls._discovery_filter_from_spec(spec.get("aws-kms-discovery-filter")), + provider_id=spec.get("provider-id"), + encryption_algorithm=spec.get("encryption-algorithm"), + padding_algorithm=spec.get("padding-algorithm"), + padding_hash=spec.get("padding-hash"), + ) + def keyring(self, keys_uri, mode): # type: (KeysManifest) -> IKeyring """Build a keyring using this specification. @@ -73,8 +107,8 @@ def keyring(self, keys_uri, mode): "key": self.key_name, "provider-id": self.provider_id, "encryption-algorithm": self.encryption_algorithm, - } + if self.padding_algorithm is not None and self.padding_algorithm != "": input_kwargs["padding-algorithm"] = self.padding_algorithm if self.padding_hash is not None: From 5e813e77e6a341dc2d5061d2d267ede45ea14a92 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 8 Aug 2024 09:34:47 -0700 Subject: [PATCH 20/51] chore(examples): Added raw RSA/AES keyring multithreaded examples (#694) --- examples/src/multithreading/__init__.py | 63 ++++++++++++++++++ .../src/multithreading/raw_aes_keyring.py | 38 +++++++++++ .../src/multithreading/raw_rsa_keyring.py | 66 +++++++++++++++++++ examples/test/multithreading/__init__.py | 3 + ...i_raw_aes_keyring_multithreaded_example.py | 50 ++++++++++++++ ...i_raw_rsa_keyring_multithreaded_example.py | 51 ++++++++++++++ 6 files changed, 271 insertions(+) create mode 100644 examples/src/multithreading/__init__.py create mode 100644 examples/src/multithreading/raw_aes_keyring.py create mode 100644 examples/src/multithreading/raw_rsa_keyring.py create mode 100644 examples/test/multithreading/__init__.py create mode 100644 examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py create mode 100644 examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py new file mode 100644 index 000000000..32210a0ab --- /dev/null +++ b/examples/src/multithreading/__init__.py @@ -0,0 +1,63 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""init file for multi-threading examples.""" +import time + +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk + + +def encrypt_and_decrypt_with_keyring( + plaintext_data: bytes, + keyring: IKeyring, + client: aws_encryption_sdk.EncryptionSDKClient +): + """Demonstrate how to encrypt and decrypt plaintext data using a keyring. + + Usage: encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + :param client: The Encryption SDK client to use for encryption. + :type client: aws_encryption_sdk.EncryptionSDKClient + :return: encrypted and decrypted (cycled) plaintext data + :rtype: bytes + """ + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=encryption_context + ) + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data + + +def run_encrypt_and_decrypt_with_keyring_for_duration_seconds( + plaintext_data: bytes, + keyring: IKeyring, + client: aws_encryption_sdk.EncryptionSDKClient, + duration: int = 2 +): + """Helper function to repeatedly run an encrypt and decrypt cycle for 'duration' seconds.""" + time_end = time.time() + duration + + while time.time() < time_end: + decrypted_plaintext_data = encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client) + assert decrypted_plaintext_data == plaintext_data, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/multithreading/raw_aes_keyring.py b/examples/src/multithreading/raw_aes_keyring.py new file mode 100644 index 000000000..42a391344 --- /dev/null +++ b/examples/src/multithreading/raw_aes_keyring.py @@ -0,0 +1,38 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This file contains methods to use for testing multi-threading for Raw AES keyring.""" + +import secrets + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + static_key = secrets.token_bytes(32) + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py new file mode 100644 index 000000000..77d26f2fc --- /dev/null +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -0,0 +1,66 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This file contains methods to use for testing multi-threading for Raw RSA keyring.""" +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa + + +def generate_rsa_keys(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + key_name_space = "Some managed raw keys" + key_name = "My 4096-bit RSA wrapping key" + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring diff --git a/examples/test/multithreading/__init__.py b/examples/test/multithreading/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/multithreading/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py new file mode 100644 index 000000000..225e3c411 --- /dev/null +++ b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py @@ -0,0 +1,50 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw AES keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed + +import pytest +# pylint and isort disagree about where this goes; listen to isort +from typing import Optional # pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +from ...src.multithreading import run_encrypt_and_decrypt_with_keyring_for_duration_seconds +from ...src.multithreading.raw_aes_keyring import create_keyring + +pytestmark = [pytest.mark.examples] + + +def encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=64, duration=60): + """Encrypt and decrypt using a keyring for fixed n_threads and duration.""" + keyring = create_keyring() + plaintext_data = b"Hello World" + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(run_encrypt_and_decrypt_with_keyring_for_duration_seconds, + plaintext_data=plaintext_data, + keyring=keyring, + client=client, + duration=duration): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + future.result() + + +def test_encrypt_and_decrypt_with_keyring_multithreaded( + n_threads_list: Optional[list] = None, + duration_list: Optional[list] = None, +): + """Test function for multi-threaded encrypt and decrypt using a keyring for different n_threads and duration.""" + # Set defaults if no value is provided + if n_threads_list is None: + n_threads_list = [1, 4, 16, 64] + if duration_list is None: + duration_list = [2, 10, 60] + for n in n_threads_list: + for d in duration_list: + encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=n, duration=d) diff --git a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py new file mode 100644 index 000000000..c1ebdbe24 --- /dev/null +++ b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py @@ -0,0 +1,51 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw RSA keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed + +import pytest +# pylint and isort disagree about where this goes; listen to isort +from typing import Optional # pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +from ...src.multithreading import run_encrypt_and_decrypt_with_keyring_for_duration_seconds +from ...src.multithreading.raw_rsa_keyring import create_keyring, generate_rsa_keys + +pytestmark = [pytest.mark.examples] + + +def encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=64, duration=60): + """Encrypt and decrypt using a keyring for fixed n_threads and duration.""" + public_key, private_key = generate_rsa_keys() + keyring = create_keyring(public_key=public_key, private_key=private_key) + plaintext_data = b"Hello World" + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(run_encrypt_and_decrypt_with_keyring_for_duration_seconds, + plaintext_data=plaintext_data, + keyring=keyring, + client=client, + duration=duration): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + future.result() + + +def test_encrypt_and_decrypt_with_keyring_multithreaded( + n_threads_list: Optional[list] = None, + duration_list: Optional[list] = None, +): + """Test function for multi-threaded encrypt and decrypt using a keyring for different n_threads and duration.""" + # Set defaults if no value is provided + if n_threads_list is None: + n_threads_list = [1, 4, 16, 64] + if duration_list is None: + duration_list = [2, 10, 60] + for n in n_threads_list: + for d in duration_list: + encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=n, duration=d) From ffe28d90d72c18fa5bc7555986c12e6813a20539 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 9 Aug 2024 11:37:47 -0700 Subject: [PATCH 21/51] merge --- .readthedocs.yaml | 9 ++- CHANGELOG.rst | 21 +++++++ cfn/ESDK-Python.yml | 4 +- codebuild/py37/decrypt_dafny_esdk_vectors.yml | 58 ------------------- codebuild/py37/decrypt_masterkey_with_js.yml | 34 ----------- .../py37/decrypt_masterkey_with_masterkey.yml | 30 ---------- codebuild/py37/decrypt_net_401_vectors.yml | 35 ----------- codebuild/py37/encrypt_masterkey.yml | 25 -------- .../generate_decrypt_vectors_masterkey.yml | 28 --------- src/aws_encryption_sdk/identifiers.py | 2 +- 10 files changed, 32 insertions(+), 214 deletions(-) delete mode 100644 codebuild/py37/decrypt_dafny_esdk_vectors.yml delete mode 100644 codebuild/py37/decrypt_masterkey_with_js.yml delete mode 100644 codebuild/py37/decrypt_masterkey_with_masterkey.yml delete mode 100644 codebuild/py37/decrypt_net_401_vectors.yml delete mode 100644 codebuild/py37/encrypt_masterkey.yml delete mode 100644 codebuild/py37/generate_decrypt_vectors_masterkey.yml diff --git a/.readthedocs.yaml b/.readthedocs.yaml index a19ab5081..82c9c983c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,6 +5,12 @@ # Required version: 2 +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.8" + # Build documentation in the doc/ directory with Sphinx sphinx: configuration: doc/conf.py @@ -15,8 +21,7 @@ submodules: exclude: all python: - version: 3.8 install: - requirements: dev_requirements/doc-requirements.txt - - method: setuptools + - method: pip path: . diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b8b3d5992..609b58c73 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,27 @@ Changelog ********* +3.3.0 -- 2024-05-20 +=================== + +Deprecation +----------- +The AWS Encryption SDK for Python no longer supports Python 3.7 +as of version 3.3; only Python 3.8+ is supported. + +Fixes +----------- +* fix: Handle errors when decrypting multiple EDKs with raw RSA MKPs (#672 (https://github.com/aws/aws-encryption-sdk-python/pull/672)) +* chore: Updated description of decrypt() usage in src/aws_encryption_sdk/__init__.py (#660 (https://github.com/aws/aws-encryption-sdk-python/pull/660)) +* fix(CI): removed appveyor.yml (#668 (https://github.com/aws/aws-encryption-sdk-python/pull/668)) +* fix(CI): updated ci_test-vector-handler.yaml and ci_tests.yaml (#665 (https://github.com/aws/aws-encryption-sdk-python/pull/665)) + +Maintenance +----------- +* feat: remove Python3.7 support (#648 (https://github.com/aws/aws-encryption-sdk-python/pull/648)) +* chore: Update copyright headers (#677 (https://github.com/aws/aws-encryption-sdk-python/pull/677)) +* chore(CFN): Changes for MPL TestVectors (#653 (https://github.com/aws/aws-encryption-sdk-python/pull/653)) + 3.2.0 -- 2024-03-18 =================== diff --git a/cfn/ESDK-Python.yml b/cfn/ESDK-Python.yml index df085ac68..acf5689c5 100644 --- a/cfn/ESDK-Python.yml +++ b/cfn/ESDK-Python.yml @@ -312,7 +312,9 @@ Resources: "Effect": "Allow", "Resource": [ "arn:aws:secretsmanager:us-west-2:587316601012:secret:TestPyPiCryptoTools-SxeLBh", - "arn:aws:secretsmanager:us-west-2:587316601012:secret:PyPiAdmin-ZWyd1T" + "arn:aws:secretsmanager:us-west-2:587316601012:secret:TestPyPiAPIToken-uERFjs", + "arn:aws:secretsmanager:us-west-2:587316601012:secret:PyPiAdmin-ZWyd1T", + "arn:aws:secretsmanager:us-west-2:587316601012:secret:PyPiAPIToken-nu1Gu6" ], "Action": "secretsmanager:GetSecretValue" } diff --git a/codebuild/py37/decrypt_dafny_esdk_vectors.yml b/codebuild/py37/decrypt_dafny_esdk_vectors.yml deleted file mode 100644 index ee2d428c7..000000000 --- a/codebuild/py37/decrypt_dafny_esdk_vectors.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: 0.2 -# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM - -env: - variables: - TOXENV: "py37-full_decrypt" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - git-credential-helper: yes - secrets-manager: - GITHUB_TOKEN: Github/lucasmcdonald3-fgpat:actions read - -phases: - install: - runtime-versions: - python: 3.7 - pre_build: - commands: - # Fetch test vectors from Dafny ESDK's most recent run - # (Assuming the first result is most recent; seems to be correct...) - - | - MOST_RECENT_RUN_ID=$(curl -H "Accept: application/vnd.github+json" \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs?branch=mainline&status=completed&page=1&exclude_pull_requests=true" \ - | jq 'first(.workflow_runs[] | select(.name=="Daily CI") | .id)') - - | - echo "DEBUG: Fetching artifact from run $MOST_RECENT_RUN_ID" - - | - MOST_RECENT_RUN_DOWNLOAD_URL=$(curl -H "Accept: application/vnd.github+json" \ - -H "Authorization: token $GITHUB_TOKEN" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/aws/aws-encryption-sdk-dafny/actions/runs/$MOST_RECENT_RUN_ID/artifacts?name=ubuntu-latest_vector_artifact" \ - | jq '.artifacts[0].archive_download_url') - - | - echo "DEBUG: Fetching artifact at $MOST_RECENT_RUN_DOWNLOAD_URL" - - | - curl -L -H "Accept: application/vnd.github+json" \ - -H "Authorization: token $GITHUB_TOKEN" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - $(echo $MOST_RECENT_RUN_DOWNLOAD_URL | tr -d '"') -o ubuntu-latest_test_vector_artifact.zip - # This unzips to `net41.zip`. - - unzip ubuntu-latest_test_vector_artifact - # This unzips to `net41/`. - - unzip net41.zip -d net41 - build: - commands: - - pip install "tox < 4.0" - - cd test_vector_handlers - - | - tox -- \ - --input ../net41/manifest.json diff --git a/codebuild/py37/decrypt_masterkey_with_js.yml b/codebuild/py37/decrypt_masterkey_with_js.yml deleted file mode 100644 index 8a44e11e7..000000000 --- a/codebuild/py37/decrypt_masterkey_with_js.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: 0.2 - -env: - variables: - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - commands: - - n 16 - # Install the Javascript ESDK run test vectors - - npm install -g @aws-crypto/integration-node - - pre_build: - commands: - # Download previously generated vectors - - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip 37_masterkey.zip - # Repackage zip in expected format - - unzip 37_masterkey.zip - - cd 37_masterkey - - zip -r vectors.zip . - build: - commands: - # Decrypt generated vectors with Javascript ESDK - - integration-node decrypt -v vectors.zip \ No newline at end of file diff --git a/codebuild/py37/decrypt_masterkey_with_masterkey.yml b/codebuild/py37/decrypt_masterkey_with_masterkey.yml deleted file mode 100644 index 1774b05f4..000000000 --- a/codebuild/py37/decrypt_masterkey_with_masterkey.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-full_decrypt" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - pre_build: - commands: - # Download previously generated vectors - - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip 37_masterkey.zip - - unzip 37_masterkey.zip - build: - commands: - - pip install "tox < 4.0" - - cd test_vector_handlers - - | - tox -- \ - --input ../37_masterkey/manifest.json \ No newline at end of file diff --git a/codebuild/py37/decrypt_net_401_vectors.yml b/codebuild/py37/decrypt_net_401_vectors.yml deleted file mode 100644 index 1dfb48ce8..000000000 --- a/codebuild/py37/decrypt_net_401_vectors.yml +++ /dev/null @@ -1,35 +0,0 @@ -version: 0.2 -# Runs Only the ESDK-NET v4.0.1 Decryption Vectors, testing Required EC CMM - -env: - variables: - TOXENV: "py37-full_decrypt" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - pre_build: - commands: - # Fetch ESDK .NET v4.0.1 Test Vectors - - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip - - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip - - curl -s --output $VECTOR_ZIP --location $VECTORS_URL - - UNZIPPED_VECTORS_DIR=$CODEBUILD_SRC_DIR/test_vector_handlers/net_401_vectors - - unzip $VECTOR_ZIP -d $UNZIPPED_VECTORS_DIR - build: - commands: - # NOTE: We need to pass the absolute path of the vectors - - pip install "tox < 4.0" - - cd $CODEBUILD_SRC_DIR/test_vector_handlers - - | - tox -- \ - --input $UNZIPPED_VECTORS_DIR/manifest.json diff --git a/codebuild/py37/encrypt_masterkey.yml b/codebuild/py37/encrypt_masterkey.yml deleted file mode 100644 index 7cdc7848e..000000000 --- a/codebuild/py37/encrypt_masterkey.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-full_encrypt" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - build: - commands: - - pip install "tox < 4.0" - - cd test_vector_handlers - - | - tox -- \ - --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0003-awses-message-encryption.v2.json diff --git a/codebuild/py37/generate_decrypt_vectors_masterkey.yml b/codebuild/py37/generate_decrypt_vectors_masterkey.yml deleted file mode 100644 index 55ec3e9e4..000000000 --- a/codebuild/py37/generate_decrypt_vectors_masterkey.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 0.2 - -env: - variables: - TOXENV: "py37-full_decrypt_generate" - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- - arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- - arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- - arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- - arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 - -phases: - install: - runtime-versions: - python: 3.7 - build: - commands: - - pip install "tox < 4.0" - - cd test_vector_handlers - - | - tox -- \ - --input test/aws-crypto-tools-test-vector-framework/features/CANONICAL-GENERATED-MANIFESTS/0006-awses-message-decryption-generation.v2.json \ - --output 37_masterkey - - zip -r 37_masterkey.zip 37_masterkey - - aws s3 cp 37_masterkey.zip s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/37_masterkey.zip diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index 84df9c751..a06030889 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -17,7 +17,7 @@ # We only actually need these imports when running the mypy checks pass -__version__ = "3.2.0" +__version__ = "3.3.0" USER_AGENT_SUFFIX = "AwsEncryptionSdkPython/{}".format(__version__) From 1c73a65925c437fee6d5ab7f3718f33ffdad7ff4 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 16 Aug 2024 15:27:51 -0700 Subject: [PATCH 22/51] test: Required encryption context CMM integration tests (#691) --- test/mpl/integ/__init__.py | 2 + test/mpl/integ/test_required_ec_cmm.py | 560 +++++++++++++++++++++++++ test/mpl/utils.py | 183 ++++++++ 3 files changed, 745 insertions(+) create mode 100644 test/mpl/integ/__init__.py create mode 100644 test/mpl/integ/test_required_ec_cmm.py create mode 100644 test/mpl/utils.py diff --git a/test/mpl/integ/__init__.py b/test/mpl/integ/__init__.py new file mode 100644 index 000000000..f94fd12a2 --- /dev/null +++ b/test/mpl/integ/__init__.py @@ -0,0 +1,2 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/test/mpl/integ/test_required_ec_cmm.py b/test/mpl/integ/test_required_ec_cmm.py new file mode 100644 index 000000000..c99528f70 --- /dev/null +++ b/test/mpl/integ/test_required_ec_cmm.py @@ -0,0 +1,560 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +import copy + +import pytest +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, + CreateRequiredEncryptionContextCMMInput, +) + +import aws_encryption_sdk +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + +from ..utils import TestEncryptionContexts, TestKeyringCreator + +pytestmark = [pytest.mark.integ] + +# ESDK client. Used to encrypt/decrypt in each test. +client = aws_encryption_sdk.EncryptionSDKClient() + +# MPL client. Used to create CMMs. +mpl_client: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() +) + + +# Keyrings under test +SOME_RSA_KEYRING = TestKeyringCreator._create_raw_rsa_keyring() +SOME_AES_KEYRING = TestKeyringCreator._create_raw_aes_keyring() +SOME_KMS_KEYRING = TestKeyringCreator._create_kms_keyring() +SOME_HIERARCHICAL_KEYRING = TestKeyringCreator._create_hierarchical_keyring() +TEST_KEYRINGS_LIST = [ + SOME_AES_KEYRING, + SOME_KMS_KEYRING, + SOME_RSA_KEYRING, + SOME_HIERARCHICAL_KEYRING, +] +# Multi-keyring composed of individual keyrings. +# In lots of tests in this file, +# this multi keyring encrypts one message, +# then the test attempts decryption with all of its component keyrings +# ("component" = generator + child keyrings). +SOME_MULTI_KEYRING = TestKeyringCreator._create_multi_keyring(TEST_KEYRINGS_LIST) + + +SOME_PLAINTEXT = b"Hello World" + + +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.ALL_ENCRYPTION_CONTEXTS) +# HAPPY CASE 1 +# Test supply same encryption context on encrypt and decrypt NO filtering +def test_GIVEN_same_EC_on_encrypt_and_decrypt_WHEN_encrypt_decrypt_cycle_THEN_decrypt_matches_plaintext( + encryption_context +): + # When: encrypt/decrypt cycle + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + keyring=SOME_MULTI_KEYRING, + # Given: same encryption context on encrypt and decrypt + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + pt, _ = client.decrypt( + source=ct, + # Given: same encryption context on encrypt and decrypt + encryption_context=encryption_context, + keyring=decrypt_keyring + ) + + # Then: decrypted plaintext matches original plaintext + assert pt == SOME_PLAINTEXT + + +# This test needs >=1 item to supply as required encryption context +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.NONEMPTY_ENCRYPTION_CONTEXTS) +# HAPPY CASE 2 +# On Encrypt we will only write one encryption context key value to the header +# we will then supply only what we didn't write wth no required ec cmm, +# This test case is checking that the default cmm is doing the correct filtering +def test_GIVEN_RECCMM_with_one_REC_key_on_encrypt_AND_default_CMM_with_valid_reproduced_EC_on_decrypt_WHEN_supply_reproduced_EC_with_REC_key_on_decrypt_THEN_decrypt_matches_plaintext( # noqa pylint: disable=line-too-long + encryption_context +): + # Grab one item from encryption_context to supply as reproduced EC + one_k, one_v = next(iter(encryption_context.items())) + reproduced_ec = {one_k: one_v} + # Given: one required encryption context (REC) key + required_ec_keys = [one_k] + + default_cmm = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm, + # Given: one required encryption context (REC) key + required_encryption_context_keys=required_ec_keys + ) + ) + + # When: encrypt/decrypt cycle + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + # Given: required encryption context CMM (RECCMM) on encrypt + materials_manager=required_ec_cmm, + # Given: encryption context with REC key on encrypt + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + pt, _ = client.decrypt( + source=ct, + # Given: default CMM on decrypt (ESDK auto-creates default CMM) + keyring=decrypt_keyring, + # When: supply valid reproduced EC (containing REC key) on decrypt + encryption_context=reproduced_ec, + ) + + # Then: decrypted plaintext matches original plaintext, no errors + assert pt == SOME_PLAINTEXT + + +# This test needs >=1 item to supply as required encryption context +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.NONEMPTY_ENCRYPTION_CONTEXTS) +# HAPPY CASE 3 +# On Encrypt we will only write one encryption context key value to the header +# we will then supply only what we didn't write but included in the signature while we +# are configured with the required encryption context cmm +def test_GIVEN_RECCMM_with_one_REC_key_on_encrypt_AND_RECCMM_with_valid_reproduced_EC_on_decrypt_WHEN_supply_reproduced_EC_with_REC_key_on_decrypt_THEN_decrypt_matches_plaintext( # noqa pylint: disable=line-too-long + encryption_context +): + # Grab one item from encryption_context to supply as reproduced EC + one_k, one_v = next(iter(encryption_context.items())) + reproduced_ec = {one_k: one_v} + # Given: one required encryption context (REC) key + required_ec_keys = [one_k] + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm_encrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_encrypt, + # Given: one required encryption context (REC) key + required_encryption_context_keys=required_ec_keys + ) + ) + + # When: encrypt/decrypt cycle + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + # Given: required encryption context CMM (RECCMM) on encrypt + materials_manager=required_ec_cmm_encrypt, + # Given: encryption context with REC key on encrypt + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + default_cmm_decrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=decrypt_keyring, + ) + ) + + required_ec_cmm_decrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + # Given: required encryption context CMM (RECCMM) on decrypt + underlying_cmm=default_cmm_decrypt, + # Given: correct required encryption context (REC) keys on decrypt + required_encryption_context_keys=required_ec_keys + ) + ) + + pt, _ = client.decrypt( + source=ct, + # Given: required encryption context CMM (RECCMM) on decrypt + materials_manager=required_ec_cmm_decrypt, + # When: supply reproduced EC on decrypt + encryption_context=reproduced_ec, + ) + + # Then: decrypted plaintext matches original plaintext + assert pt == SOME_PLAINTEXT + + +# This test needs >=1 item to supply as required encryption context +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.NONEMPTY_ENCRYPTION_CONTEXTS) +# HAPPY CASE 4 +# On Encrypt we write all encryption context +# as if the message was encrypted before the feature existed. +# We will then have a required encryption context cmm +# that will require us to supply the encryption context on decrypt. +def test_GIVEN_default_CMM_on_encrypt_AND_default_CMM_with_valid_reproduced_EC_on_decrypt_WHEN_supply_reproduced_EC_with_REC_key_on_decrypt_THEN_decrypt_matches_plaintext( # noqa pylint: disable=line-too-long + encryption_context +): + # Grab one item from encryption_context to supply as reproduced EC + one_k, one_v = next(iter(encryption_context.items())) + reproduced_ec = {one_k: one_v} + # Given: one required encryption context (REC) key + required_ec_keys = [one_k] + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + # When: encrypt/decrypt cycle + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + # Given: default CMM on encrypt + materials_manager=default_cmm_encrypt, + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + default_cmm_decrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=decrypt_keyring, + ) + ) + + required_ec_cmm_decrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_decrypt, + # Given: one required encryption context (REC) key + required_encryption_context_keys=required_ec_keys + ) + ) + + pt, _ = client.decrypt( + source=ct, + # Given: required encryption context CMM (RECCMM) on decrypt + materials_manager=required_ec_cmm_decrypt, + # When: supply reproduced EC on decrypt + encryption_context=reproduced_ec, + ) + + # Then: decrypted plaintext matches original plaintext + assert pt == SOME_PLAINTEXT + + +# This test needs >=2 items in EC so it can swap their key/value pairs +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.AT_LEAST_TWO_ITEMS_ENCRYPTION_CONTEXTS) +# FAILURE CASE 1 +# Encrypt with and store all encryption context in header +# On Decrypt supply additional encryption context not stored in the header; this MUST fail +# On Decrypt supply mismatched encryption context key values; this MUST fail +def test_GIVEN_default_CMM_with_EC_on_encrypt_AND_default_CMM_with_different_EC_on_decrypt_WHEN_decrypt_THEN_raise_AWSEncryptionSDKClientError( # noqa pylint: disable=line-too-long + encryption_context, +): + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + keyring=SOME_MULTI_KEYRING, + encryption_context=encryption_context, + ) + + # Create some different ECs to test failure on decrypt + + # Swap one key/value pair to create a "mismatched" EC + ec_iter = iter(encryption_context.items()) + one_k, one_v = next(ec_iter) + two_k, two_v = next(ec_iter) + some_mismatched_ec = copy.deepcopy(encryption_context) + some_mismatched_ec[one_k] = two_v + some_mismatched_ec[two_k] = one_v + + # Some other encryption context where its key/value pair is not in the encryption context on encrypt + some_reproduced_ec_not_in_ec = {"this is not in": "the original encryption context"} + + for decrypt_keyring in TEST_KEYRINGS_LIST: + # Then: decrypting with mismatched EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=decrypt_keyring, + # Given: different encryption context on decrypt + encryption_context=some_mismatched_ec, + ) + + # Then: decrypting with some other EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=decrypt_keyring, + # Given: different encryption context on decrypt + encryption_context=some_reproduced_ec_not_in_ec, + ) + + +# This test needs >=1 item to supply as required encryption context +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.NONEMPTY_ENCRYPTION_CONTEXTS) +# FAILURE CASE 2 +# Encrypt will not store all Encryption Context, we will drop one entry but it will still get +# included in the +# header signture. +# Decrypt will not supply any reproduced Encryption Context; this MUST fail. +def test_GIVEN_RECCCMM_with_one_REC_key_on_encrypt_AND_default_CMM_with_no_EC_on_decrypt_WHEN_decrypt_THEN_raise_AWSEncryptionSDKClientError( # noqa pylint: disable=line-too-long + encryption_context, +): + # Grab one item from encryption_context to supply as reproduced EC + one_k, _ = next(iter(encryption_context.items())) + # Given: one required encryption context (REC) key + required_ec_keys = [one_k] + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm_encrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_encrypt, + # Given: one required encryption context (REC) key + required_encryption_context_keys=required_ec_keys + ) + ) + + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + materials_manager=required_ec_cmm_encrypt, + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + # Then: decrypting with no EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=decrypt_keyring, + # Given: no encryption context on decrypt + ) + + +# This test needs >=1 item to supply as required encryption context +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.NONEMPTY_ENCRYPTION_CONTEXTS) +# FAILURE CASE 3 +# Encrypt will not store all Encryption Context, we will drop one entry but it will still get +# included in the +# header signture. +# Decrypt will supply the correct key but incorrect value; this MUST fail. +def test_GIVEN_RECCMM_on_encrypt_AND_EC_with_wrong_value_for_key_on_decrypt_WHEN_decrypt_THEN_raise_AWSEncryptionSDKClientError( # noqa pylint: disable=line-too-long + encryption_context, +): + # Grab one item from encryption_context to supply as reproduced EC + one_k, _ = next(iter(encryption_context.items())) + # Given: one required encryption context (REC) key + required_ec_keys = [one_k] + # Create mismatched EC + some_mismatched_ec = copy.deepcopy(encryption_context) + some_mismatched_ec[one_k] = "some incorrect value NOT in the original encryption context" + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm_encrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_encrypt, + required_encryption_context_keys=required_ec_keys + ) + ) + + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + materials_manager=required_ec_cmm_encrypt, + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + # Then: decrypting with mismatched EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=decrypt_keyring, + # Given: encryption context with wrong value for required key on decrypt + encryption_context=some_mismatched_ec, + ) + + +# This test needs >=2 items in EC so it create incorrect reproduced EC scenarios +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.AT_LEAST_TWO_ITEMS_ENCRYPTION_CONTEXTS) +# FAILURE CASE 4 +# Encrypt will not store all Encryption Context, we will drop one entry but it will still get +# included in the +# header signture. +# Decrypt will supply the correct key but incorrect value; this MUST fail. +def test_GIVEN_RECCMM_on_encrypt_AND_reproduced_EC_missing_REC_key_on_decrypt_WHEN_decrypt_THEN_raise_AWSEncryptionSDKClientError( # noqa pylint: disable=line-too-long + encryption_context, +): + # Grab one item from encryption_context to supply as reproduced EC + ec_iter = iter(encryption_context.items()) + required_k, _ = next(ec_iter) + required_ec_keys = [required_k] + # Grab another item to use as the reproduced EC + # where the key in reproduced EC is not in required encryption context keys + some_other_k, some_other_v = next(ec_iter) + incorrect_reproduced_ec = {some_other_k : some_other_v} + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm_encrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_encrypt, + required_encryption_context_keys=required_ec_keys + ) + ) + + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + materials_manager=required_ec_cmm_encrypt, + encryption_context=encryption_context, + ) + + for decrypt_keyring in TEST_KEYRINGS_LIST: + # Then: decrypting with invalid EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=decrypt_keyring, + # Given: encryption context on decrypt does not have required EC key + encryption_context=incorrect_reproduced_ec, + ) + + +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.ALL_ENCRYPTION_CONTEXTS) +# FAILURE CASE 5 +# Although we are requesting that we remove a RESERVED key word from the encryption context +# The CMM instantiation will still succeed because the CMM is meant to work with different +# higher level +# encryption libraries who may have different reserved keys. Encryption will ultimately fail. +def test_GIVEN_RECCMM_with_reserved_key_on_encrypt_WHEN_encrypt_THEN_raise_AWSEncryptionSDKClientError( + encryption_context +): + invalid_encryption_context = copy.deepcopy(encryption_context) + # Add reserved EC item to encryption context to make it invalid + reserved_ec_keyword = "aws-crypto-public-key" + invalid_encryption_context[reserved_ec_keyword] = "some value in reserved key" + required_ec_keys = [reserved_ec_keyword] + + default_cmm_encrypt = mpl_client.create_default_cryptographic_materials_manager( + CreateDefaultCryptographicMaterialsManagerInput( + keyring=SOME_MULTI_KEYRING, + ) + ) + + required_ec_cmm_encrypt = mpl_client.create_required_encryption_context_cmm( + CreateRequiredEncryptionContextCMMInput( + underlying_cmm=default_cmm_encrypt, + # Given: required encryption context keys has a reserved value + required_encryption_context_keys=required_ec_keys + ) + ) + + # Then: encrypting with reserved key in encryption context raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: encrypt + client.encrypt( + source=SOME_PLAINTEXT, + materials_manager=required_ec_cmm_encrypt, + encryption_context=invalid_encryption_context, + ) + + +# This test needs >=2 items in EC so it create invalid reproduced EC scenarios +@pytest.mark.parametrize("encryption_context", TestEncryptionContexts.AT_LEAST_TWO_ITEMS_ENCRYPTION_CONTEXTS) +@pytest.mark.parametrize("keyring", TEST_KEYRINGS_LIST) +def test_GIVEN_some_keyring_AND_some_EC_WHEN_decrypt_valid_message_with_mutated_EC_THEN_decryption_matches_expected_result( # noqa pylint: disable=line-too-long + keyring, + encryption_context, +): + # Additional EC + some_additional_ec = copy.deepcopy(encryption_context) + some_additional_ec["some extra key to add"] = "some extra value added" + + # Mismatched EC. Swap key/value pair to create a mismatched EC + ec_iter = iter(encryption_context.items()) + one_k, one_v = next(ec_iter) + two_k, two_v = next(ec_iter) + some_mismatched_ec = copy.deepcopy(encryption_context) + some_mismatched_ec[one_k] = two_v + some_mismatched_ec[two_k] = one_v + + ct, _ = client.encrypt( + source=SOME_PLAINTEXT, + # Given: some keyring + keyring=keyring, + # Given: some encryption context + encryption_context=encryption_context, + ) + + # Expected failure: incorrect EC + + # Then: decrypting with incorrect EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=keyring, + # Given: incorrect encryption context with an extra item + encryption_context=some_additional_ec, + ) + + # Expected failure: Mismatched EC (swapped value for 2 keys) + + # Then: decrypting with mismatched EC raises AWSEncryptionSDKClientError + with pytest.raises(AWSEncryptionSDKClientError): + # When: decrypt + client.decrypt( + source=ct, + keyring=keyring, + # Given: mismatched encryption context on decrypt + encryption_context=some_mismatched_ec, + ) + + # Expected success: No encryption context supplied on decrypt + # (Success because the message was not encrypted with required EC CMM) + + # When: decrypt + pt, _ = client.decrypt( + source=ct, + keyring=keyring, + # Given: no encryption context on decrypt + ) + + # Then: decrypted plaintext matches original plaintext + assert pt == SOME_PLAINTEXT + + # Expected success: Correct encryption context supplied on decrypt + + # When: decrypt + pt, _ = client.decrypt( + source=ct, + keyring=keyring, + # Given: no encryption context on decrypt + encryption_context=encryption_context, + ) + + # Then: decrypted plaintext matches original plaintext + assert pt == SOME_PLAINTEXT diff --git a/test/mpl/utils.py b/test/mpl/utils.py new file mode 100644 index 000000000..0809aace4 --- /dev/null +++ b/test/mpl/utils.py @@ -0,0 +1,183 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +import random +import secrets +import string + +import boto3 +from aws_cryptographic_materialproviders.keystore import KeyStore +from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig +from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + AesWrappingAlg, + CacheTypeDefault, + CreateAwsKmsHierarchicalKeyringInput, + CreateAwsKmsKeyringInput, + CreateMultiKeyringInput, + CreateRawAesKeyringInput, + CreateRawRsaKeyringInput, + DefaultCache, + PaddingScheme, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa + +# MPL client. Used to create keyrings. +mpl_client: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() +) + + +class TestKeyringCreator: + + # Private raw AES keyring creator. + # Lifted from raw AES keyring example. + @staticmethod + def _create_raw_aes_keyring(): + static_key = secrets.token_bytes(32) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace="some_key_namespace", + key_name="some_key_name", + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + raw_aes_keyring: IKeyring = mpl_client.create_raw_aes_keyring( + input=keyring_input + ) + + return raw_aes_keyring + + # Private raw RSA keyring creator. + # Lifted from raw RSA keyring example. + @staticmethod + def _create_raw_rsa_keyring(): + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + key_name_space = "some_key_name_space" + key_name = "some_key_name" + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + raw_rsa_keyring: IKeyring = mpl_client.create_raw_rsa_keyring( + input=keyring_input + ) + + return raw_rsa_keyring + + # Private KMS keyring creator. + # Lifted KMS keyring example. + @staticmethod + def _create_kms_keyring(): + kms_client = boto3.client('kms', region_name="us-west-2") + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id="arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f", + kms_client=kms_client + ) + + kms_keyring: IKeyring = mpl_client.create_aws_kms_keyring( + input=keyring_input + ) + + return kms_keyring + + # Private hierarchical keyring creator. + # Lifted hierarchical keyring example. + @staticmethod + def _create_hierarchical_keyring(): + kms_client = boto3.client('kms', region_name="us-west-2") + ddb_client = boto3.client('dynamodb', region_name="us-west-2") + + keystore: KeyStore = KeyStore( + config=KeyStoreConfig( + ddb_client=ddb_client, + ddb_table_name="KeyStoreDdbTable", + logical_key_store_name="KeyStoreDdbTable", + kms_client=kms_client, + kms_configuration=KMSConfigurationKmsKeyArn( + value='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126' + ), + ) + ) + + keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id='a52dfaad-7dbd-4430-a1fd-abaa5299da07', + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + hierarchical_keyring: IKeyring = mpl_client.create_aws_kms_hierarchical_keyring( + input=keyring_input + ) + + return hierarchical_keyring + + # Private multi-keyring creator. + @staticmethod + def _create_multi_keyring(keyrings): + a = mpl_client.create_multi_keyring(CreateMultiKeyringInput( + generator=keyrings[0], + child_keyrings=keyrings[1:] + )) + return a + + +class TestEncryptionContexts: + + # Encryption contexts under test + SOME_EMPTY_ENCRYPTION_CONTEXT = {} + SOME_SINGLE_ITEM_ENCRYPTION_CONTEXT = {"some_key": "some_value"} + SOME_DOUBLE_ITEM_ENCRYPTION_CONTEXT = {"some_key": "some_value", "some_other_key": "some_other_value"} + SOME_MANY_ITEM_ENCRYPTION_CONTEXT = { + ''.join(random.choices(string.ascii_letters, k=6)) + : ''.join(random.choices(string.ascii_letters, k=6)) for _ in range(20) + } + ALL_ENCRYPTION_CONTEXTS = [ + SOME_EMPTY_ENCRYPTION_CONTEXT, + SOME_SINGLE_ITEM_ENCRYPTION_CONTEXT, + SOME_DOUBLE_ITEM_ENCRYPTION_CONTEXT, + SOME_MANY_ITEM_ENCRYPTION_CONTEXT, + ] + + NONEMPTY_ENCRYPTION_CONTEXTS = [ + SOME_SINGLE_ITEM_ENCRYPTION_CONTEXT, + SOME_DOUBLE_ITEM_ENCRYPTION_CONTEXT, + SOME_MANY_ITEM_ENCRYPTION_CONTEXT, + ] + + AT_LEAST_TWO_ITEMS_ENCRYPTION_CONTEXTS = [ + SOME_DOUBLE_ITEM_ENCRYPTION_CONTEXT, + SOME_MANY_ITEM_ENCRYPTION_CONTEXT, + ] From 1df7dbc3f3f322294547e58e84f836ec986f4c77 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 19 Aug 2024 13:06:07 -0700 Subject: [PATCH 23/51] fix(Examples): Validate EC on decrypt (#697) --- .../src/aws_kms_discovery_keyring_example.py | 19 +++++------ ...aws_kms_discovery_multi_keyring_example.py | 14 +++----- examples/src/aws_kms_keyring_example.py | 14 +++----- .../aws_kms_mrk_discovery_keyring_example.py | 14 +++----- ...kms_mrk_discovery_multi_keyring_example.py | 14 +++----- examples/src/aws_kms_mrk_keyring_example.py | 14 +++----- .../src/aws_kms_mrk_multi_keyring_example.py | 32 +++++++---------- examples/src/aws_kms_multi_keyring_example.py | 12 +++++-- examples/src/aws_kms_rsa_keyring_example.py | 14 +++----- ...cryptographic_materials_manager_example.py | 14 +++----- examples/src/file_streaming_example.py | 6 ---- examples/src/hierarchical_keyring_example.py | 21 +++++++++--- .../migration_aws_kms_key_example.py | 34 +++++++++++++++---- .../migration_raw_aes_key_example.py | 34 +++++++++++++++---- .../migration_raw_rsa_key_example.py | 34 +++++++++++++++---- ...migration_set_commitment_policy_example.py | 14 +++----- examples/src/multi_keyring_example.py | 12 +++++-- examples/src/multithreading/__init__.py | 4 ++- examples/src/raw_aes_keyring_example.py | 14 +++----- examples/src/raw_rsa_keyring_example.py | 23 ++++++------- .../set_encryption_algorithm_suite_example.py | 14 +++----- 21 files changed, 203 insertions(+), 168 deletions(-) diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index d78121bc3..cef894360 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -153,18 +153,14 @@ def encrypt_and_decrypt_with_keyring( # successfully decrypted. The resulting data key is used to decrypt the # ciphertext's message. # If all calls to KMS fail, the decryption fails. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=discovery_keyring + keyring=discovery_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 9. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" @@ -192,7 +188,10 @@ def encrypt_and_decrypt_with_keyring( try: plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=discovery_keyring_bob + keyring=discovery_keyring_bob, + # Verify that the encryption context in the result contains the + # encryption context supplied to the encrypt method + encryption_context=encryption_context, ) raise AssertionError("Decrypt using discovery keyring with wrong AWS Account ID should" diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 9381a740b..82454cc34 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -151,18 +151,14 @@ def encrypt_and_decrypt_with_keyring( # All of this is done serially, until a success occurs or all keyrings have # failed all (filtered) EDKs. # KMS Discovery Keyrings will attempt to decrypt Multi Region Keys (MRKs) and regular KMS Keys. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=discovery_multi_keyring + keyring=discovery_multi_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 9. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index 8977e3750..5b07e5210 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -97,18 +97,14 @@ def encrypt_and_decrypt_with_keyring( "Ciphertext and plaintext data are the same. Invalid encryption" # 7. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=kms_keyring + keyring=kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index 23d6cb322..fecc332f9 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -163,17 +163,13 @@ def encrypt_and_decrypt_with_keyring( ) # 7. Decrypt your encrypted data using the discovery keyring. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=decrypt_discovery_keyring + keyring=decrypt_discovery_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index adb249e2a..ef02caa61 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -172,17 +172,13 @@ def encrypt_and_decrypt_with_keyring( # All of this is done serially, until a success occurs or all keyrings have failed # all (filtered) EDKs. KMS MRK Discovery Keyrings will attempt to decrypt # Multi Region Keys (MRKs) and regular KMS Keys. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=decrypt_discovery_keyring + keyring=decrypt_discovery_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index edb3cc410..ee7f570f0 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -132,18 +132,14 @@ def encrypt_and_decrypt_with_keyring( ) # 7. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=decrypt_keyring + keyring=decrypt_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 6b1e64eec..71ee0f00b 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -124,18 +124,14 @@ def encrypt_and_decrypt_with_keyring( # 6. Decrypt your encrypted data using the same AwsKmsMrkMultiKeyring you used on encrypt. # It will decrypt the data using the generator key (in this case, the MRK), since that is # the first available KMS key on the keyring that is capable of decrypting the data. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=kms_mrk_multi_keyring + keyring=kms_mrk_multi_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 7. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 7. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" @@ -144,7 +140,7 @@ def encrypt_and_decrypt_with_keyring( # multi-keyring used to encrypt the data is also capable of decrypting the data. # (This is an example for demonstration; you do not need to do this in your own code.) - # 9. Create a single AwsKmsMrkKeyring with the replica KMS MRK from the second region. + # 8. Create a single AwsKmsMrkKeyring with the replica KMS MRK from the second region. # Create a boto3 client for KMS in the second region which is the region for mrk_replica_key_id. second_region_kms_client = boto3.client('kms', region_name=mrk_replica_decrypt_region) @@ -158,19 +154,15 @@ def encrypt_and_decrypt_with_keyring( input=second_region_mrk_keyring_input ) - # 10. Decrypt your encrypted data using the second region AwsKmsMrkKeyring - plaintext_bytes_second_region, dec_header_second_region = client.decrypt( + # 9. Decrypt your encrypted data using the second region AwsKmsMrkKeyring + plaintext_bytes_second_region, _ = client.decrypt( source=ciphertext, - keyring=second_region_mrk_keyring + keyring=second_region_mrk_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 11. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header_second_region.encryption_context[k], \ - "Encryption context does not match expected values" - - # 12. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes_second_region == EXAMPLE_DATA diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index 7cba36167..4e74eafc8 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -133,7 +133,9 @@ def encrypt_and_decrypt_with_keyring( # 6a. Decrypt your encrypted data using the same multi_keyring you used on encrypt. plaintext_bytes_multi_keyring, _ = client.decrypt( source=ciphertext, - keyring=kms_multi_keyring + keyring=kms_multi_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 6b. Demonstrate that the decrypted plaintext is identical to the original plaintext. @@ -164,7 +166,9 @@ def encrypt_and_decrypt_with_keyring( # 7c. Decrypt your encrypted data using the default_region_kms_keyring. plaintext_bytes_default_region_kms_keyring, _ = client.decrypt( source=ciphertext, - keyring=default_region_kms_keyring + keyring=default_region_kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 7d. Demonstrate that the decrypted plaintext is identical to the original plaintext. @@ -192,7 +196,9 @@ def encrypt_and_decrypt_with_keyring( # 8c. Decrypt your encrypted data using the second_region_kms_keyring. plaintext_bytes_second_region_kms_keyring, _ = client.decrypt( source=ciphertext, - keyring=second_region_kms_keyring + keyring=second_region_kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 8d. Demonstrate that the decrypted plaintext is identical to the original plaintext. diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index fd05fc20b..81c613c99 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -103,18 +103,14 @@ def encrypt_and_decrypt_with_keyring( "Ciphertext and plaintext data are the same. Invalid encryption" # 7. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=kms_rsa_keyring + keyring=kms_rsa_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py index 15a9f22cf..f6312e208 100644 --- a/examples/src/default_cryptographic_materials_manager_example.py +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -109,18 +109,14 @@ def encrypt_and_decrypt_with_default_cmm( "Ciphertext and plaintext data are the same. Invalid encryption" # 7. Decrypt your encrypted data using the same cmm you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - materials_manager=cmm + materials_manager=cmm, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index 3f547d220..c7c3cff05 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -134,12 +134,6 @@ def encrypt_and_decrypt_with_keyring( for chunk in decryptor: pt_file.write(chunk) - # 9. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == decryptor.header.encryption_context[k], \ - "Encryption context does not match expected values" - # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert filecmp.cmp(plaintext_filename, decrypted_filename), \ diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index 00dadf9d8..92efa2865 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -200,7 +200,10 @@ def encrypt_and_decrypt_with_keyring( try: client.decrypt( source=ciphertext_a, - keyring=hierarchical_keyring_b + keyring=hierarchical_keyring_b, + # Verify that the encryption context in the result contains the + # encryption context supplied to the encrypt method + encryption_context=encryption_context_a, ) except AWSEncryptionSDKClientError: pass @@ -210,22 +213,30 @@ def encrypt_and_decrypt_with_keyring( try: client.decrypt( source=ciphertext_b, - keyring=hierarchical_keyring_a + keyring=hierarchical_keyring_a, + # Verify that the encryption context in the result contains the + # encryption context supplied to the encrypt method + encryption_context=encryption_context_b, ) except AWSEncryptionSDKClientError: pass - # 10. Demonstrate that data encrypted by one tenant's branch key can be decrypted by that tenant, + # 11. Demonstrate that data encrypted by one tenant's branch key can be decrypted by that tenant, # and that the decrypted data matches the input data. plaintext_bytes_a, _ = client.decrypt( source=ciphertext_a, - keyring=hierarchical_keyring_a + keyring=hierarchical_keyring_a, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context_a, ) assert plaintext_bytes_a == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" + plaintext_bytes_b, _ = client.decrypt( source=ciphertext_b, - keyring=hierarchical_keyring_b + keyring=hierarchical_keyring_b, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context_b, ) assert plaintext_bytes_b == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py index 28b8193e3..e0a577d20 100644 --- a/examples/src/migration/migration_aws_kms_key_example.py +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -115,14 +115,14 @@ def migration_aws_kms_key( aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id) # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring - ciphertext_keyring, _ = client.encrypt( + ciphertext_keyring, encrypted_header_keyring = client.encrypt( source=EXAMPLE_DATA, keyring=aws_kms_keyring, encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider - ciphertext_mkp, _ = client.encrypt( + ciphertext_mkp, encrypted_header_mkp = client.encrypt( source=EXAMPLE_DATA, key_provider=aws_kms_master_key_provider, encryption_context=DEFAULT_ENCRYPTION_CONTEXT @@ -137,14 +137,25 @@ def migration_aws_kms_key( # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( source=ciphertext_keyring, - keyring=aws_kms_keyring + keyring=aws_kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + decrypted_ciphertext_keyring_using_mkp, decrypted_header_keyring_using_mkp = client.decrypt( source=ciphertext_keyring, key_provider=aws_kms_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_keyring_using_mkp.encryption_context.items() + for pair in encrypted_header_keyring.encryption_context.items() + ) + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" @@ -153,14 +164,25 @@ def migration_aws_kms_key( # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( source=ciphertext_mkp, - keyring=aws_kms_keyring + keyring=aws_kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + decrypted_ciphertext_mkp_using_mkp, decrypted_header_mkp_using_mkp = client.decrypt( source=ciphertext_mkp, key_provider=aws_kms_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_mkp_using_mkp.encryption_context.items() + for pair in encrypted_header_mkp.encryption_context.items() + ) + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 772f83cf5..4bd15d1f9 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -156,14 +156,14 @@ def migration_raw_aes_key(): raw_aes_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring - ciphertext_keyring, _ = client.encrypt( + ciphertext_keyring, encrypted_header_keyring = client.encrypt( source=EXAMPLE_DATA, keyring=raw_aes_keyring, encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider - ciphertext_mkp, _ = client.encrypt( + ciphertext_mkp, encrypted_header_mkp = client.encrypt( source=EXAMPLE_DATA, key_provider=raw_aes_master_key_provider, encryption_context=DEFAULT_ENCRYPTION_CONTEXT @@ -178,14 +178,25 @@ def migration_raw_aes_key(): # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( source=ciphertext_keyring, - keyring=raw_aes_keyring + keyring=raw_aes_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + decrypted_ciphertext_keyring_using_mkp, decrypted_header_keyring_using_mkp = client.decrypt( source=ciphertext_keyring, key_provider=raw_aes_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_keyring_using_mkp.encryption_context.items() + for pair in encrypted_header_keyring.encryption_context.items() + ) + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" @@ -194,14 +205,25 @@ def migration_raw_aes_key(): # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( source=ciphertext_mkp, - keyring=raw_aes_keyring + keyring=raw_aes_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + decrypted_ciphertext_mkp_using_mkp, decrypted_header_mkp_using_mkp = client.decrypt( source=ciphertext_mkp, key_provider=raw_aes_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_mkp_using_mkp.encryption_context.items() + for pair in encrypted_header_mkp.encryption_context.items() + ) + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 7c6020a53..22c9512ec 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -208,14 +208,14 @@ def migration_raw_rsa_key( raw_rsa_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring - ciphertext_keyring, _ = client.encrypt( + ciphertext_keyring, encrypted_header_keyring = client.encrypt( source=EXAMPLE_DATA, keyring=raw_rsa_keyring, encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider - ciphertext_mkp, _ = client.encrypt( + ciphertext_mkp, encrypted_header_mkp = client.encrypt( source=EXAMPLE_DATA, key_provider=raw_rsa_master_key_provider, encryption_context=DEFAULT_ENCRYPTION_CONTEXT @@ -230,14 +230,25 @@ def migration_raw_rsa_key( # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( source=ciphertext_keyring, - keyring=raw_rsa_keyring + keyring=raw_rsa_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + decrypted_ciphertext_keyring_using_mkp, decrypted_header_keyring_using_mkp = client.decrypt( source=ciphertext_keyring, key_provider=raw_rsa_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_keyring_using_mkp.encryption_context.items() + for pair in encrypted_header_keyring.encryption_context.items() + ) + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" @@ -246,14 +257,25 @@ def migration_raw_rsa_key( # resulting plaintext is the same and also equal to EXAMPLE_DATA decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( source=ciphertext_mkp, - keyring=raw_rsa_keyring + keyring=raw_rsa_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=DEFAULT_ENCRYPTION_CONTEXT, ) - decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + decrypted_ciphertext_mkp_using_mkp, decrypted_header_mkp_using_mkp = client.decrypt( source=ciphertext_mkp, key_provider=raw_rsa_master_key_provider ) + # Legacy MasterKeyProviders do not support providing encryption context on decrypt. + # If decrypting with a legacy MasterKeyProvider, you should manually verify + # that the encryption context used in the decrypt operation + # includes all key pairs from the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + assert all( + pair in decrypted_header_mkp_using_mkp.encryption_context.items() + for pair in encrypted_header_mkp.encryption_context.items() + ) + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 3851df0e2..5598e9575 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -105,18 +105,14 @@ def encrypt_and_decrypt_with_keyring( "Ciphertext and plaintext data are the same. Invalid encryption" # 7. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=kms_keyring + keyring=kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 8. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index 20af7ba81..f55b2aeca 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -164,7 +164,9 @@ def encrypt_and_decrypt_with_keyring( # 10a. Decrypt your encrypted data using the same multi_keyring you used on encrypt. plaintext_bytes_multi_keyring, _ = client.decrypt( source=ciphertext, - keyring=multi_keyring + keyring=multi_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 10b. Demonstrate that the decrypted plaintext is identical to the original plaintext. @@ -182,7 +184,9 @@ def encrypt_and_decrypt_with_keyring( # 11a. Decrypt your encrypted data using the kms_keyring. plaintext_bytes_kms_keyring, _ = client.decrypt( source=ciphertext, - keyring=kms_keyring + keyring=kms_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 11b. Demonstrate that the decrypted plaintext is identical to the original plaintext. @@ -197,7 +201,9 @@ def encrypt_and_decrypt_with_keyring( # 12a. Decrypt your encrypted data using the raw_aes_keyring. plaintext_bytes_raw_aes_keyring, _ = client.decrypt( source=ciphertext, - keyring=raw_aes_keyring + keyring=raw_aes_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) # 12b. Demonstrate that the decrypted plaintext is identical to the original plaintext. diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py index 32210a0ab..4fdad58fd 100644 --- a/examples/src/multithreading/__init__.py +++ b/examples/src/multithreading/__init__.py @@ -42,7 +42,9 @@ def encrypt_and_decrypt_with_keyring( decrypted_plaintext_data, _ = client.decrypt( source=ciphertext_data, - keyring=keyring + keyring=keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) return decrypted_plaintext_data diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index ab9603af6..8d6dd9513 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -107,18 +107,14 @@ def encrypt_and_decrypt_with_keyring(): "Ciphertext and plaintext data are the same. Invalid encryption" # 8. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=raw_aes_keyring + keyring=raw_aes_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 9. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 1200a7c72..3a47dfe8e 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -205,18 +205,14 @@ def encrypt_and_decrypt_with_keyring(public_key_file_name=None, private_key_file "Ciphertext and plaintext data are the same. Invalid encryption" # 6. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=raw_rsa_keyring + keyring=raw_rsa_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 7. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 8. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 7. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" @@ -225,18 +221,21 @@ def encrypt_and_decrypt_with_keyring(public_key_file_name=None, private_key_file # decryption of the original ciphertext is not possible with a different keyring (Bob's). # (This is an example for demonstration; you do not need to do this in your own code.) - # 9. Create a new Raw RSA keyring for Bob + # 8. Create a new Raw RSA keyring for Bob # Generate new keys public_key_bob, private_key_bob = generate_rsa_keys() # Create the keyring raw_rsa_keyring_bob = create_rsa_keyring(public_key=public_key_bob, private_key=private_key_bob) - # 10. Test decrypt for the original ciphertext using raw_rsa_keyring_bob + # 9. Test decrypt for the original ciphertext using raw_rsa_keyring_bob try: plaintext_bytes_bob, _ = client.decrypt( # pylint: disable=unused-variable source=ciphertext, - keyring=raw_rsa_keyring_bob + keyring=raw_rsa_keyring_bob, + # Verify that the encryption context in the result contains the + # encryption context supplied to the encrypt method + encryption_context=encryption_context, ) raise AssertionError("client.decrypt should throw an error of type AWSEncryptionSDKClientError!") diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index 75eaee85a..bbe5be58a 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -128,18 +128,14 @@ def encrypt_and_decrypt_with_keyring(): "Ciphertext and plaintext data are the same. Invalid encryption" # 8. Decrypt your encrypted data using the same keyring you used on encrypt. - plaintext_bytes, dec_header = client.decrypt( + plaintext_bytes, _ = client.decrypt( source=ciphertext, - keyring=raw_aes_keyring + keyring=raw_aes_keyring, + # Provide the encryption context that was supplied to the encrypt method + encryption_context=encryption_context, ) - # 9. Demonstrate that the encryption context is correct in the decrypted message header - # (This is an example for demonstration; you do not need to do this in your own code.) - for k, v in encryption_context.items(): - assert v == dec_header.encryption_context[k], \ - "Encryption context does not match expected values" - - # 10. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. # (This is an example for demonstration; you do not need to do this in your own code.) assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" From 91aca72c46e168f7e465769ee7e62dfaeba41790 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 6 Sep 2024 08:51:06 -0700 Subject: [PATCH 24/51] chore: Refer to renamed MPL libraries (#698) --- performance_tests/requirements_mpl.txt | 2 +- requirements_mpl.txt | 2 +- setup.py | 4 ++-- test_vector_handlers/requirements_mpl.txt | 2 +- .../awses_test_vectors/internal/mpl/keyvectors_provider.py | 4 ++-- .../src/awses_test_vectors/manifests/mpl_keyring.py | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index 28d7dc356..d9744a723 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-materialproviders @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 28d7dc356..5cbdb37a1 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-materialproviders @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python diff --git a/setup.py b/setup.py index c069bade1..3af72f984 100644 --- a/setup.py +++ b/setup.py @@ -43,9 +43,9 @@ def get_requirements(): # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ - "MPL": ["aws-cryptographic-material-providers @" \ + "MPL": ["aws-cryptographic-materialproviders @" \ "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ - "lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + "python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], }, classifiers=[ "Development Status :: 5 - Production/Stable", diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt index 1aab5f534..6cffc62e6 100644 --- a/test_vector_handlers/requirements_mpl.txt +++ b/test_vector_handlers/requirements_mpl.txt @@ -1 +1 @@ -amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptography-internal-mpl-testvectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py b/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py index 305459026..90581182c 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/mpl/keyvectors_provider.py @@ -1,11 +1,11 @@ """Singleton provider for the KeyVectors client.""" # # Ignore missing MPL TestVectors for pylint, but the MPL TestVectors is required for this file # pylint: disable=import-error -from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ +from aws_cryptography_materialproviders_test_vectors.smithygenerated.\ aws_cryptography_materialproviderstestvectorkeys.client import ( KeyVectors, ) -from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ +from aws_cryptography_materialproviders_test_vectors.smithygenerated.\ aws_cryptography_materialproviderstestvectorkeys.config import ( KeyVectorsConfig ) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py index dbabeb3c7..f2ea05559 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -19,7 +19,7 @@ # Ignore missing MPL for pylint, but the MPL is required for this example # noqa pylint: disable=import-error -from aws_cryptography_materialproviderstestvectorkeys.smithygenerated.\ +from aws_cryptography_materialproviders_test_vectors.smithygenerated.\ aws_cryptography_materialproviderstestvectorkeys.models import ( GetKeyDescriptionInput, GetKeyDescriptionOutput, @@ -31,7 +31,7 @@ from aws_cryptographic_materialproviders.mpl.models import CreateMultiKeyringInput import _dafny -from standard_library.internaldafny.generated import UTF8 +from smithy_dafny_standard_library.internaldafny.generated import UTF8 # Ignore pylint not being able to read a module that requires the MPL # pylint: disable=no-name-in-module From 0f19a45db6a17cfcfc4f2a51962c00afd44d2ded Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 2 Oct 2024 12:48:12 -0700 Subject: [PATCH 25/51] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index fa6effb1f..72d72cc26 100644 --- a/README.rst +++ b/README.rst @@ -42,7 +42,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: >= TODO.TODO.TODO (TODO-MPL: versionme) +* aws-cryptographic-material-providers: >= 1.8.0 (TODO-MPL: versionme) * Requires Python 3.11+. Installation From 219c9055c1fc6399be6e9cfa23eb86da73dd7733 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 3 Oct 2024 10:13:26 -0700 Subject: [PATCH 26/51] fix(CI): Fix oracle linting (#702) --- decrypt_oracle/.chalice/pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/decrypt_oracle/.chalice/pipeline.py b/decrypt_oracle/.chalice/pipeline.py index 9d5573646..de8ee1b9c 100644 --- a/decrypt_oracle/.chalice/pipeline.py +++ b/decrypt_oracle/.chalice/pipeline.py @@ -145,6 +145,7 @@ def _cloudformation_role() -> iam.Role: ) +# pylint: disable=too-many-positional-arguments def _pipeline( pipeline_role: iam.Role, cfn_role: iam.Role, From 45f386ec38143b5bf93b3baa1b44ff5f70eb354d Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 4 Oct 2024 16:17:45 -0700 Subject: [PATCH 27/51] fix(test): Fix building ESDK-Net (#703) --- codebuild/py312/decrypt_hkeyring_with_net.yml | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/codebuild/py312/decrypt_hkeyring_with_net.yml b/codebuild/py312/decrypt_hkeyring_with_net.yml index 6a3b321eb..1a1ab1827 100644 --- a/codebuild/py312/decrypt_hkeyring_with_net.yml +++ b/codebuild/py312/decrypt_hkeyring_with_net.yml @@ -23,27 +23,26 @@ phases: - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest.zip - unzip 312_hkeyring_reccmm_manifest.zip - export DAFNY_AWS_ESDK_TEST_VECTOR_MANIFEST_PATH="${PWD}/312_hkeyring_reccmm_manifest/manifest.json" - - # Download dafny - - curl https://github.com/dafny-lang/dafny/releases/download/v4.7.0/dafny-4.7.0-x64-ubuntu-20.04.zip -L -o dafny.zip + + # Clone SDK-Dafny repo to get test vectors runner source code and the Dafny version to use + - git clone --recurse-submodules https://github.com/aws/aws-encryption-sdk-dafny.git + # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file + - export dafnyVersion=$(grep '^dafnyVersion=' aws-encryption-sdk-dafny/AwsEncryptionSDK/project.properties | cut -d '=' -f 2) + - curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip - unzip -qq dafny.zip && rm dafny.zip - export PATH="$PWD/dafny:$PATH" - # Clone SDK-Dafny repo to get test vectors runner - - git clone --recurse-submodules https://github.com/aws/aws-encryption-sdk-dafny.git - # TODO: Change branch to published when available - - cd aws-encryption-sdk-dafny - - git checkout lucmcdon/hkeyring-vectors - - git pull - - cd AwsEncryptionSDK/ - - make transpile_net - - cd ../mpl/TestVectorsAwsCryptographicMaterialProviders/ + # Build MPL test vector runner from source + - cd aws-encryption-sdk-dafny/mpl/TestVectorsAwsCryptographicMaterialProviders/ - make transpile_net - # Change TestVectors to reference the published .NET ESDK - - cd ../../AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors - # - sed -i -e 's///g' AWSEncryptionSDKTestVectorLib.csproj - # - cd ../TestVectors + # Change ESDK TestVectors project to reference the published .NET ESDK + - cd ../../AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib + # CodeBuild seems to want to use ESDK-NET 4.0.0, which is not the most recent version... + # Pin to at least 4.1.0; this is the most recent version at time of writing. + # Hopefully CodeBuild will find more recent versions in the future + - sed -i 's|||g' AWSEncryptionSDKTestVectorLib.csproj + - cd ../TestVectors build: commands: From 5b2b116ceda3ab0849d5b4587ad2b5ebc3ee2cc8 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:51:27 -0700 Subject: [PATCH 28/51] chore(examples): fix comments (#705) --- examples/src/aws_kms_discovery_keyring_example.py | 9 ++++----- examples/src/aws_kms_discovery_multi_keyring_example.py | 3 +-- examples/src/aws_kms_keyring_example.py | 3 +-- examples/src/aws_kms_mrk_discovery_keyring_example.py | 3 +-- .../src/aws_kms_mrk_discovery_multi_keyring_example.py | 3 +-- examples/src/aws_kms_mrk_keyring_example.py | 3 +-- examples/src/aws_kms_mrk_multi_keyring_example.py | 5 ++--- examples/src/aws_kms_rsa_keyring_example.py | 3 +-- .../default_cryptographic_materials_manager_example.py | 3 +-- examples/src/file_streaming_example.py | 3 +-- .../migration/migration_set_commitment_policy_example.py | 3 +-- examples/src/raw_aes_keyring_example.py | 3 +-- examples/src/raw_rsa_keyring_example.py | 5 ++--- examples/src/set_encryption_algorithm_suite_example.py | 3 +-- 14 files changed, 19 insertions(+), 33 deletions(-) diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index cef894360..3baa668d4 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -23,9 +23,8 @@ with an encryption context. This encrypted ciphertext is then decrypted using the Discovery keyring. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA -4. Decryption is only possible if the Discovery Keyring contains the correct AWS Account ID's to +2. Decrypted plaintext value matches EXAMPLE_DATA +3. Decryption is only possible if the Discovery Keyring contains the correct AWS Account ID's to which the KMS key used for encryption belongs These sanity checks are for demonstration in the example only. You do not need these in your code. @@ -165,8 +164,8 @@ def encrypt_and_decrypt_with_keyring( assert plaintext_bytes == EXAMPLE_DATA, \ "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" - # 11. Demonstrate that if a discovery keyring (Bob's) doesn't have the correct AWS Account ID's, - # the decrypt will fail with an error message + # 10. Demonstrate that if a different discovery keyring (Bob's) doesn't have the correct + # AWS Account ID's, the decrypt will fail with an error message # Note that this assumes Account ID used here ('888888888888') is different than the one used # during encryption discovery_keyring_input_bob: CreateAwsKmsDiscoveryKeyringInput = \ diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 82454cc34..d07d499b2 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -22,8 +22,7 @@ with an encryption context. This encrypted ciphertext is then decrypted using the Discovery Multi keyring. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For more information on how to use KMS Discovery keyrings, see diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index 5b07e5210..dc18dadc2 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -7,8 +7,7 @@ decrypt data keys. This example creates a KMS Keyring and then encrypts a custom input EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. AWS KMS keyrings can be used independently or in a multi-keyring with other keyrings diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index fecc332f9..a93552532 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -21,8 +21,7 @@ with an encryption context. This encrypted ciphertext is then decrypted using an MRK Discovery keyring. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For information about using multi-Region keys with the AWS Encryption SDK, see diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index ef02caa61..958683a19 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -23,8 +23,7 @@ with an encryption context. This encrypted ciphertext is then decrypted using an MRK Discovery Multi keyring. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For information about using multi-Region keys with the AWS Encryption SDK, see diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index ee7f570f0..8611a6120 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -8,8 +8,7 @@ This example creates a KMS MRK Keyring and then encrypts a custom input EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. AWS KMS MRK keyrings can be used independently or in a multi-keyring with other keyrings diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 71ee0f00b..9c32affb8 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -14,9 +14,8 @@ Either KMS Key individually is capable of decrypting data encrypted under this keyring. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA -4. Ciphertext can be decrypted using an AwsKmsMrkKeyring containing a replica of the +2. Decrypted plaintext value matches EXAMPLE_DATA +3. Ciphertext can be decrypted using an AwsKmsMrkKeyring containing a replica of the MRK (from the multi-keyring used for encryption) copied from the first region into the second region These sanity checks are for demonstration in the example only. You do not need these in your code. diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index 81c613c99..e86ea6973 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -7,8 +7,7 @@ EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. # For more information on how to use KMS keyrings, see diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py index f6312e208..091e79ada 100644 --- a/examples/src/default_cryptographic_materials_manager_example.py +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -11,8 +11,7 @@ and we use an AWS KMS Keyring for this example. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For more information on Cryptographic Material Managers, see diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index c7c3cff05..debbb6859 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -13,8 +13,7 @@ It then decrypts the ciphertext from `ciphertext_filename` to a new file `decrypted_filename`. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For more information on how to use Raw AES keyrings, see diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 5598e9575..81506e710 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -13,8 +13,7 @@ with an encryption context for the commitment policy FORBID_ENCRYPT_ALLOW_DECRYPT. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For more information on setting your commitment policy, see diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index 8d6dd9513..a28c350ff 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -11,8 +11,7 @@ This example creates a Raw AES Keyring and then encrypts a custom input EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. The Raw AES keyring encrypts data by using the AES-GCM algorithm and a wrapping key that diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 3a47dfe8e..22101bb57 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -15,9 +15,8 @@ This example creates a Raw RSA Keyring and then encrypts a custom input EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA -4. The original ciphertext is not decryptable using a keyring with a different RSA key pair +2. Decrypted plaintext value matches EXAMPLE_DATA +3. The original ciphertext is not decryptable using a keyring with a different RSA key pair These sanity checks are for demonstration in the example only. You do not need these in your code. A Raw RSA keyring that encrypts and decrypts must include an asymmetric public key and private diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index bbe5be58a..95c7a0938 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -31,8 +31,7 @@ with an encryption context and the algorithm suite AES_256_GCM_HKDF_SHA512_COMMIT_KEY. This example also includes some sanity checks for demonstration: 1. Ciphertext and plaintext data are not the same -2. Encryption context is correct in the decrypted message header -3. Decrypted plaintext value matches EXAMPLE_DATA +2. Decrypted plaintext value matches EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. For more information on how to use Raw AES keyrings, see From ea82181426587525c7ea6ca2e83cf767c32bd643 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 23 Oct 2024 13:06:38 -0700 Subject: [PATCH 29/51] chore(MPL): Rename MPL Python package (#706) --- .../src/aws_kms_discovery_keyring_example.py | 8 +-- ...aws_kms_discovery_multi_keyring_example.py | 8 +-- examples/src/aws_kms_keyring_example.py | 8 +-- .../aws_kms_mrk_discovery_keyring_example.py | 8 +-- ...kms_mrk_discovery_multi_keyring_example.py | 8 +-- examples/src/aws_kms_mrk_keyring_example.py | 8 +-- .../src/aws_kms_mrk_multi_keyring_example.py | 11 ++-- examples/src/aws_kms_multi_keyring_example.py | 8 +-- examples/src/aws_kms_rsa_keyring_example.py | 8 +-- .../src/branch_key_id_supplier_example.py | 4 +- examples/src/custom_mpl_cmm_example.py | 16 +++--- ...cryptographic_materials_manager_example.py | 8 +-- examples/src/file_streaming_example.py | 8 +-- examples/src/hierarchical_keyring_example.py | 14 +++--- .../migration_aws_kms_key_example.py | 8 +-- .../migration_raw_aes_key_example.py | 8 +-- .../migration_raw_rsa_key_example.py | 8 +-- ...migration_set_commitment_policy_example.py | 8 +-- examples/src/multi_keyring_example.py | 8 +-- examples/src/multithreading/__init__.py | 2 +- .../src/multithreading/raw_aes_keyring.py | 8 +-- .../src/multithreading/raw_rsa_keyring.py | 8 +-- examples/src/raw_aes_keyring_example.py | 8 +-- examples/src/raw_rsa_keyring_example.py | 8 +-- .../src/required_encryption_context_cmm.py | 10 ++-- .../set_encryption_algorithm_suite_example.py | 8 +-- .../test/test_i_custom_mpl_cmm_example.py | 8 +-- performance_tests/requirements_mpl.txt | 2 +- .../keyrings/aws_kms_keyring.py | 8 +-- .../keyrings/hierarchy_keyring.py | 14 +++--- .../keyrings/raw_aes_keyring.py | 8 +-- .../keyrings/raw_rsa_keyring.py | 8 +-- requirements_mpl.txt | 2 +- setup.py | 4 +- src/aws_encryption_sdk/__init__.py | 28 +++++------ .../internal/formatting/serialize.py | 6 +-- src/aws_encryption_sdk/key_providers/base.py | 7 +-- .../materials_managers/__init__.py | 2 +- .../materials_managers/mpl/cmm.py | 8 +-- .../materials_managers/mpl/materials.py | 6 +-- src/aws_encryption_sdk/streaming_client.py | 26 +++++----- test/mpl/integ/test_required_ec_cmm.py | 6 +-- .../unit/test_material_managers_mpl_cmm.py | 6 +-- .../test_material_managers_mpl_materials.py | 2 +- test/mpl/utils.py | 14 +++--- test/unit/test_streaming_client_configs.py | 2 +- test/unit/test_streaming_client_mpl_import.py | 2 +- test_vector_handlers/requirements_mpl.txt | 2 +- .../commands/full_message_decrypt.py | 2 +- .../commands/full_message_decrypt_generate.py | 2 +- .../commands/full_message_encrypt.py | 2 +- .../internal/mpl/tampering_mpl_materials.py | 6 +-- .../manifests/full_message/decrypt.py | 8 +-- .../full_message/decrypt_generation.py | 8 +-- .../manifests/full_message/encrypt.py | 2 +- .../manifests/master_key.py | 50 ++++++++++++++++--- .../manifests/mpl_keyring.py | 8 +-- 57 files changed, 259 insertions(+), 217 deletions(-) diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index 3baa668d4..ba02b62a7 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -33,14 +33,14 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsDiscoveryKeyringInput, CreateAwsKmsKeyringInput, DiscoveryFilter, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index d07d499b2..5dd85f99c 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -30,14 +30,14 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsDiscoveryMultiKeyringInput, CreateAwsKmsKeyringInput, DiscoveryFilter, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index dc18dadc2..8590b35ef 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -18,10 +18,10 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index a93552532..a88e1ae20 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -35,14 +35,14 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsMrkDiscoveryKeyringInput, CreateAwsKmsMrkKeyringInput, DiscoveryFilter, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index 958683a19..26412e2b2 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -37,14 +37,14 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsMrkDiscoveryMultiKeyringInput, CreateAwsKmsMrkKeyringInput, DiscoveryFilter, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index 8611a6120..1cadfec45 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -22,10 +22,10 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsMrkKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 9c32affb8..d9514d961 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -28,10 +28,13 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMrkKeyringInput, CreateAwsKmsMrkMultiKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( + CreateAwsKmsMrkKeyringInput, + CreateAwsKmsMrkMultiKeyringInput, +) +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index 4e74eafc8..69928ccd7 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -38,10 +38,10 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput, CreateAwsKmsMultiKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput, CreateAwsKmsMultiKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index e86ea6973..4750660eb 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -15,10 +15,10 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsRsaKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsRsaKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/branch_key_id_supplier_example.py b/examples/src/branch_key_id_supplier_example.py index b25d9abeb..a14e8eae3 100644 --- a/examples/src/branch_key_id_supplier_example.py +++ b/examples/src/branch_key_id_supplier_example.py @@ -2,8 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 """Example implementation of a branch key ID supplier.""" -from aws_cryptographic_materialproviders.mpl.models import GetBranchKeyIdInput, GetBranchKeyIdOutput -from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier +from aws_cryptographic_material_providers.mpl.models import GetBranchKeyIdInput, GetBranchKeyIdOutput +from aws_cryptographic_material_providers.mpl.references import IBranchKeyIdSupplier from typing import Dict # noqa pylint: disable=wrong-import-order diff --git a/examples/src/custom_mpl_cmm_example.py b/examples/src/custom_mpl_cmm_example.py index 544ca5f00..b9a8f043f 100644 --- a/examples/src/custom_mpl_cmm_example.py +++ b/examples/src/custom_mpl_cmm_example.py @@ -23,13 +23,13 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager """ -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateDefaultCryptographicMaterialsManagerInput, SignatureAlgorithmNone, ) -from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from aws_cryptographic_material_providers.mpl.references import ICryptographicMaterialsManager, IKeyring import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy @@ -65,10 +65,10 @@ def __init__(self, keyring: IKeyring, cmm: ICryptographicMaterialsManager = None def get_encryption_materials(self, param): """Provides encryption materials appropriate for the request for the custom CMM. - :param aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsInput param: Input object to + :param aws_cryptographic_material_providers.mpl.models.GetEncryptionMaterialsInput param: Input object to provide to a crypto material manager's `get_encryption_materials` method. :returns: Encryption materials output - :rtype: aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsOutput + :rtype: aws_cryptographic_material_providers.mpl.models.GetEncryptionMaterialsOutput """ materials = self.underlying_cmm.get_encryption_materials(param) if isinstance(materials.encryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): @@ -81,10 +81,10 @@ def get_encryption_materials(self, param): def decrypt_materials(self, param): """Provides decryption materials appropriate for the request for the custom CMM. - :param aws_cryptographic_materialproviders.mpl.models.DecryptMaterialsInput param: Input object to provide + :param aws_cryptographic_material_providers.mpl.models.DecryptMaterialsInput param: Input object to provide to a crypto material manager's `decrypt_materials` method. :returns: Decryption materials output - :rtype: aws_cryptographic_materialproviders.mpl.models.GetDecryptionMaterialsOutput + :rtype: aws_cryptographic_material_providers.mpl.models.GetDecryptionMaterialsOutput """ materials = self.underlying_cmm.decrypt_materials(param) if isinstance(materials.decryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py index 091e79ada..e60b1cea7 100644 --- a/examples/src/default_cryptographic_materials_manager_example.py +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -18,13 +18,13 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsKeyringInput, CreateDefaultCryptographicMaterialsManagerInput, ) -from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from aws_cryptographic_material_providers.mpl.references import ICryptographicMaterialsManager, IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index debbb6859..56953f667 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -25,10 +25,10 @@ import filecmp import secrets -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index 92efa2865..a325491e3 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -35,17 +35,17 @@ import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example # noqa pylint: disable=import-error -from aws_cryptographic_materialproviders.keystore import KeyStore -from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig -from aws_cryptographic_materialproviders.keystore.models import CreateKeyInput, KMSConfigurationKmsKeyArn -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.keystore import KeyStore +from aws_cryptographic_material_providers.keystore.config import KeyStoreConfig +from aws_cryptographic_material_providers.keystore.models import CreateKeyInput, KMSConfigurationKmsKeyArn +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CacheTypeDefault, CreateAwsKmsHierarchicalKeyringInput, DefaultCache, ) -from aws_cryptographic_materialproviders.mpl.references import IBranchKeyIdSupplier, IKeyring +from aws_cryptographic_material_providers.mpl.references import IBranchKeyIdSupplier, IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py index e0a577d20..c46c6f1c9 100644 --- a/examples/src/migration/migration_aws_kms_key_example.py +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -21,10 +21,10 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 4bd15d1f9..c00ec489e 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -26,10 +26,10 @@ """ import secrets -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 22c9512ec..8d4d3f322 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -28,10 +28,10 @@ For more information on how to use Raw RSA keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html """ -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_material_providers.mpl.references import IKeyring from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 81506e710..b698fd3ab 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -21,10 +21,10 @@ """ import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index f55b2aeca..2465c7c04 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -39,15 +39,15 @@ import secrets import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( AesWrappingAlg, CreateAwsKmsKeyringInput, CreateMultiKeyringInput, CreateRawAesKeyringInput, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py index 4fdad58fd..6ac3d9a33 100644 --- a/examples/src/multithreading/__init__.py +++ b/examples/src/multithreading/__init__.py @@ -3,7 +3,7 @@ """init file for multi-threading examples.""" import time -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/multithreading/raw_aes_keyring.py b/examples/src/multithreading/raw_aes_keyring.py index 42a391344..65e4627b1 100644 --- a/examples/src/multithreading/raw_aes_keyring.py +++ b/examples/src/multithreading/raw_aes_keyring.py @@ -4,10 +4,10 @@ import secrets -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring def create_keyring(): diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py index 77d26f2fc..06d2fe679 100644 --- a/examples/src/multithreading/raw_rsa_keyring.py +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -1,10 +1,10 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """This file contains methods to use for testing multi-threading for Raw RSA keyring.""" -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_material_providers.mpl.references import IKeyring from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index a28c350ff..0e0b53491 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -23,10 +23,10 @@ """ import secrets -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 22101bb57..e59a9581c 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -33,10 +33,10 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html """ -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_material_providers.mpl.references import IKeyring from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa diff --git a/examples/src/required_encryption_context_cmm.py b/examples/src/required_encryption_context_cmm.py index edbb3f414..8edf7545e 100644 --- a/examples/src/required_encryption_context_cmm.py +++ b/examples/src/required_encryption_context_cmm.py @@ -10,14 +10,14 @@ import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example # noqa pylint: disable=import-error -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateAwsKmsKeyringInput, CreateDefaultCryptographicMaterialsManagerInput, CreateRequiredEncryptionContextCMMInput, ) -from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from aws_cryptographic_material_providers.mpl.references import ICryptographicMaterialsManager, IKeyring from typing import Dict, List # noqa pylint: disable=wrong-import-order import aws_encryption_sdk @@ -142,7 +142,7 @@ def encrypt_and_decrypt_with_keyring( try: plaintext_bytes_a, _ = client.decrypt( source=ciphertext, - materials_manager=required_ec_cmm, + materials_manager=underlying_cmm, # No reproduced encryption context for required EC CMM-produced message makes decryption fail. ) raise Exception("If this exception is raised, decryption somehow succeeded!") diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index 95c7a0938..f6df411aa 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -39,10 +39,10 @@ """ import secrets -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk diff --git a/examples/test/test_i_custom_mpl_cmm_example.py b/examples/test/test_i_custom_mpl_cmm_example.py index d98b6b6b9..6791914c4 100644 --- a/examples/test/test_i_custom_mpl_cmm_example.py +++ b/examples/test/test_i_custom_mpl_cmm_example.py @@ -3,10 +3,10 @@ """Test suite for encryption and decryption using custom CMM.""" import boto3 import pytest -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from ..src.custom_mpl_cmm_example import MPLCustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index d9744a723..9d72dfb8e 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-materialproviders @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py index e846ec695..c05409ca4 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py @@ -4,10 +4,10 @@ import aws_encryption_sdk import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring def create_keyring( diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py index b1bdc6913..8ee7b8992 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py @@ -4,17 +4,17 @@ import aws_encryption_sdk import boto3 -from aws_cryptographic_materialproviders.keystore import KeyStore -from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig -from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.keystore import KeyStore +from aws_cryptographic_material_providers.keystore.config import KeyStoreConfig +from aws_cryptographic_material_providers.keystore.models import KMSConfigurationKmsKeyArn +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CacheTypeDefault, CreateAwsKmsHierarchicalKeyringInput, DefaultCache, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from ..utils.util import PerfTestUtils diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py index a2a3c9ab1..08be9d216 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py @@ -3,10 +3,10 @@ """Performance tests for the Raw AES keyring.""" import aws_encryption_sdk -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_material_providers.mpl.references import IKeyring from ..utils.util import PerfTestUtils diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py index 6eed281bd..48894330e 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py @@ -2,10 +2,10 @@ # SPDX-License-Identifier: Apache-2.0 """Performance tests for the Raw RSA keyring.""" import aws_encryption_sdk -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_material_providers.mpl.references import IKeyring def create_keyring(public_key, private_key): diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 5cbdb37a1..9d72dfb8e 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-materialproviders @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python diff --git a/setup.py b/setup.py index 3af72f984..6260c1ad2 100644 --- a/setup.py +++ b/setup.py @@ -43,9 +43,9 @@ def get_requirements(): # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ - "MPL": ["aws-cryptographic-materialproviders @" \ + "MPL": ["aws-cryptographic-material-providers @" \ "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ - "python-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + "python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], }, classifiers=[ "Development Status :: 5 - Production/Stable", diff --git a/src/aws_encryption_sdk/__init__.py b/src/aws_encryption_sdk/__init__.py index 9f3525349..326dacc13 100644 --- a/src/aws_encryption_sdk/__init__.py +++ b/src/aws_encryption_sdk/__init__.py @@ -96,10 +96,10 @@ def encrypt(self, **kwargs): .. code:: python >>> import boto3 - >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput - >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring + >>> from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_material_providers.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( @@ -129,7 +129,7 @@ def encrypt(self, **kwargs): :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider :param keyring: `IKeyring` that returns keyring for encryption (requires either `materials_manager` or `keyring`) - :type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring + :type keyring: aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -164,10 +164,10 @@ def decrypt(self, **kwargs): .. code:: python >>> import boto3 - >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput - >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring + >>> from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_material_providers.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( @@ -197,7 +197,7 @@ def decrypt(self, **kwargs): :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider :param keyring: `IKeyring` that returns keyring for encryption (requires either `materials_manager` or `keyring`) - :type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring + :type keyring: aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -238,10 +238,10 @@ def stream(self, **kwargs): .. code:: python >>> import boto3 - >>> from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - >>> from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - >>> from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput - >>> from aws_cryptographic_materialproviders.mpl.references import IKeyring + >>> from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + >>> from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + >>> from aws_cryptographic_material_providers.mpl.models import CreateAwsKmsKeyringInput + >>> from aws_cryptographic_material_providers.mpl.references import IKeyring >>> import aws_encryption_sdk >>> client = aws_encryption_sdk.EncryptionSDKClient() >>> mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( diff --git a/src/aws_encryption_sdk/internal/formatting/serialize.py b/src/aws_encryption_sdk/internal/formatting/serialize.py index f2920a1ac..c9679a08d 100644 --- a/src/aws_encryption_sdk/internal/formatting/serialize.py +++ b/src/aws_encryption_sdk/internal/formatting/serialize.py @@ -196,7 +196,7 @@ def _serialize_header_auth_v1( :type signer: aws_encryption_sdk.Signer :param required_encryption_context_bytes: Serialized encryption context items for all items whose keys are in the required_encryption_context list. - This is ONLY processed if using the aws-cryptographic-materialproviders library + This is ONLY processed if using the aws-cryptographic-material-providers library AND its required encryption context CMM. (optional) :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data @@ -250,7 +250,7 @@ def _serialize_header_auth_v2( :type signer: aws_encryption_sdk.Signer :param required_encryption_context_bytes: Serialized encryption context items for all items whose keys are in the required_encryption_context list. - This is ONLY processed if using the aws-cryptographic-materialproviders library + This is ONLY processed if using the aws-cryptographic-material-providers library AND its required encryption context CMM. (optional) :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data @@ -306,7 +306,7 @@ def serialize_header_auth( :type signer: aws_encryption_sdk.Signer :param required_encryption_context_bytes: Serialized encryption context items for all items whose keys are in the required_encryption_context list. - This is ONLY processed if using the aws-cryptographic-materialproviders library + This is ONLY processed if using the aws-cryptographic-material-providers library AND its required encryption context CMM. (optional) :type required_encryption_context_bytes: bytes :returns: Serialized header authentication data diff --git a/src/aws_encryption_sdk/key_providers/base.py b/src/aws_encryption_sdk/key_providers/base.py index a855ee596..5fa99cc1c 100644 --- a/src/aws_encryption_sdk/key_providers/base.py +++ b/src/aws_encryption_sdk/key_providers/base.py @@ -12,6 +12,7 @@ ConfigMismatchError, DecryptKeyError, IncorrectMasterKeyError, + InvalidDataKeyError, InvalidKeyIdError, MasterKeyProviderError, ) @@ -256,7 +257,7 @@ def decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context): # //# input encryption context. data_key = master_key.decrypt_data_key(encrypted_data_key, algorithm, encryption_context) - except (IncorrectMasterKeyError, DecryptKeyError) as error: + except (IncorrectMasterKeyError, DecryptKeyError, InvalidDataKeyError) as error: _LOGGER.debug( "%s raised when attempting to decrypt data key with master key %s", repr(error), @@ -304,8 +305,8 @@ def decrypt_data_key_from_list(self, encrypted_data_keys, algorithm, encryption_ try: data_key = self.decrypt_data_key(encrypted_data_key, algorithm, encryption_context) # MasterKeyProvider.decrypt_data_key throws DecryptKeyError - # but MasterKey.decrypt_data_key throws IncorrectMasterKeyError - except (DecryptKeyError, IncorrectMasterKeyError): + # but MasterKey.decrypt_data_key throws IncorrectMasterKeyError and InvalidDataKeyError + except (DecryptKeyError, IncorrectMasterKeyError, InvalidDataKeyError): continue else: break diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 706770405..3d03e1f30 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -80,7 +80,7 @@ class DecryptionMaterialsRequest(object): :type encrypted_data_keys: set of `aws_encryption_sdk.structures.EncryptedDataKey` :param dict encryption_context: Encryption context to provide to master keys for underlying decrypt requests :param dict reproduced_encryption_context: Encryption context to provide on decrypt. - This is ONLY processed if using a CMM from the aws-cryptographic-materialproviders library. + This is ONLY processed if using a CMM from the aws-cryptographic-material-providers library. """ algorithm = attr.ib(validator=attr.validators.instance_of(Algorithm)) diff --git a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py index 49a743f89..430417c0d 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/cmm.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/cmm.py @@ -7,11 +7,11 @@ # pylint should pass even if the MPL isn't installed # Also thinks these imports aren't used if it can't import them # noqa pylint: disable=import-error,unused-import -from aws_cryptographic_materialproviders.mpl.errors import ( +from aws_cryptographic_material_providers.mpl.errors import ( AwsCryptographicMaterialProvidersException, CollectionOfErrors, ) -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl.models import ( AlgorithmSuiteIdESDK as MPL_AlgorithmSuiteIdESDK, CommitmentPolicyESDK as MPL_CommitmentPolicyESDK, DecryptMaterialsInput as MPL_DecryptMaterialsInput, @@ -20,7 +20,7 @@ GetEncryptionMaterialsInput as MPL_GetEncryptionMaterialsInput, GetEncryptionMaterialsOutput as MPL_GetEncryptionMaterialsOutput, ) -from aws_cryptographic_materialproviders.mpl.references import ( +from aws_cryptographic_material_providers.mpl.references import ( ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, ) # noqa pylint: enable=import-error,unused-import @@ -38,7 +38,7 @@ class CryptoMaterialsManagerFromMPL(CryptoMaterialsManager): """ In instances where encryption materials are provided by an implementation of the MPL's - `aws_cryptographic_materialproviders.mpl.references.MPL_ICryptographicMaterialsManager`, + `aws_cryptographic_material_providers.mpl.references.MPL_ICryptographicMaterialsManager`, this maps the ESDK-Python CMM interfaces to the MPL CMM. """ diff --git a/src/aws_encryption_sdk/materials_managers/mpl/materials.py b/src/aws_encryption_sdk/materials_managers/mpl/materials.py index 54ea21b39..c2ae305ed 100644 --- a/src/aws_encryption_sdk/materials_managers/mpl/materials.py +++ b/src/aws_encryption_sdk/materials_managers/mpl/materials.py @@ -6,7 +6,7 @@ """ # pylint should pass even if the MPL isn't installed # noqa pylint: disable=import-error -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl.models import ( DecryptionMaterials as MPL_DecryptionMaterials, EncryptedDataKey as MPL_EncryptedDataKey, EncryptionMaterials as MPL_EncryptionMaterials, @@ -30,7 +30,7 @@ def _mpl_algorithm_id_to_native_algorithm_id(mpl_algorithm_id: str) -> int: class EncryptionMaterialsFromMPL(Native_EncryptionMaterials): """ In instances where encryption materials are be provided by - the MPL's `aws_cryptographic_materialproviders.mpl.models.EncryptionMaterials`, + the MPL's `aws_cryptographic_material_providers.mpl.models.EncryptionMaterials`, this maps the ESDK interfaces to the underlying MPL materials. """ @@ -107,7 +107,7 @@ def required_encryption_context_keys(self) -> bytes: class DecryptionMaterialsFromMPL(Native_DecryptionMaterials): """ In instances where decryption materials are be provided by - the MPL's `aws_cryptographic_materialproviders.mpl.models.DecryptionMaterials`, + the MPL's `aws_cryptographic_material_providers.mpl.models.DecryptionMaterials`, this maps the ESDK interfaces to the underlying MPL materials. """ diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 64d77b91a..0eb5670b4 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -63,11 +63,11 @@ try: # pylint should pass even if the MPL isn't installed # noqa pylint: disable=import-error - from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException - from aws_cryptographic_materialproviders.mpl.models import CreateDefaultCryptographicMaterialsManagerInput - from aws_cryptographic_materialproviders.mpl.references import ( + from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + from aws_cryptographic_material_providers.mpl.errors import AwsCryptographicMaterialProvidersException + from aws_cryptographic_material_providers.mpl.models import CreateDefaultCryptographicMaterialsManagerInput + from aws_cryptographic_material_providers.mpl.references import ( ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, IKeyring as MPL_IKeyring, ) @@ -425,10 +425,10 @@ class EncryptorConfig(_ClientConfig): :param key_provider: `MasterKeyProvider` from which to obtain data keys for encryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + :param keyring: `IKeyring` from the aws_cryptographic_material_providers library which handles encryption and decryption :type keyring: - aws_cryptographic_materialproviders.mpl.references.IKeyring + aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -480,10 +480,10 @@ class StreamEncryptor(_EncryptionStream): # pylint: disable=too-many-instance-a :param key_provider: `MasterKeyProvider` from which to obtain data keys for encryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + :param keyring: `IKeyring` from the aws_cryptographic_material_providers library which handles encryption and decryption :type keyring: - aws_cryptographic_materialproviders.mpl.references.IKeyring + aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -867,10 +867,10 @@ class DecryptorConfig(_ClientConfig): :param key_provider: `MasterKeyProvider` from which to obtain data keys for decryption (either `keyring`, `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + :param keyring: `IKeyring` from the aws_cryptographic_material_providers library which handles encryption and decryption :type keyring: - aws_cryptographic_materialproviders.mpl.references.IKeyring + aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: @@ -915,10 +915,10 @@ class StreamDecryptor(_EncryptionStream): # pylint: disable=too-many-instance-a :param key_provider: `MasterKeyProvider` from which to obtain data keys for decryption (either `materials_manager` or `key_provider` required) :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param keyring: `IKeyring` from the aws_cryptographic_materialproviders library + :param keyring: `IKeyring` from the aws_cryptographic_material_providers library which handles encryption and decryption :type keyring: - aws_cryptographic_materialproviders.mpl.references.IKeyring + aws_cryptographic_material_providers.mpl.references.IKeyring :param int source_length: Length of source data (optional) .. note:: diff --git a/test/mpl/integ/test_required_ec_cmm.py b/test/mpl/integ/test_required_ec_cmm.py index c99528f70..ab308ed54 100644 --- a/test/mpl/integ/test_required_ec_cmm.py +++ b/test/mpl/integ/test_required_ec_cmm.py @@ -3,9 +3,9 @@ import copy import pytest -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateDefaultCryptographicMaterialsManagerInput, CreateRequiredEncryptionContextCMMInput, ) diff --git a/test/mpl/unit/test_material_managers_mpl_cmm.py b/test/mpl/unit/test_material_managers_mpl_cmm.py index 603446550..e8d6ceb8b 100644 --- a/test/mpl/unit/test_material_managers_mpl_cmm.py +++ b/test/mpl/unit/test_material_managers_mpl_cmm.py @@ -6,8 +6,8 @@ """ import pytest -from aws_cryptographic_materialproviders.mpl.errors import AwsCryptographicMaterialProvidersException -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl.errors import AwsCryptographicMaterialProvidersException +from aws_cryptographic_material_providers.mpl.models import ( AlgorithmSuiteIdESDK as MPL_AlgorithmSuiteIdESDK, CommitmentPolicyESDK as MPL_CommitmentPolicyESDK, DecryptionMaterials as MPL_DecryptionMaterials, @@ -16,7 +16,7 @@ GetEncryptionMaterialsInput as MPL_GetEncryptionMaterialsInput, GetEncryptionMaterialsOutput as MPL_GetEncryptionMaterialsOutput, ) -from aws_cryptographic_materialproviders.mpl.references import ( +from aws_cryptographic_material_providers.mpl.references import ( ICryptographicMaterialsManager as MPL_ICryptographicMaterialsManager, ) from mock import MagicMock, patch diff --git a/test/mpl/unit/test_material_managers_mpl_materials.py b/test/mpl/unit/test_material_managers_mpl_materials.py index 8d9052c0a..0466a6424 100644 --- a/test/mpl/unit/test_material_managers_mpl_materials.py +++ b/test/mpl/unit/test_material_managers_mpl_materials.py @@ -6,7 +6,7 @@ """ import pytest -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl.models import ( DecryptionMaterials as MPL_DecryptionMaterials, EncryptedDataKey as MPL_EncryptedDataKey, EncryptionMaterials as MPL_EncryptionMaterials, diff --git a/test/mpl/utils.py b/test/mpl/utils.py index 0809aace4..a3168c02c 100644 --- a/test/mpl/utils.py +++ b/test/mpl/utils.py @@ -5,12 +5,12 @@ import string import boto3 -from aws_cryptographic_materialproviders.keystore import KeyStore -from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig -from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.keystore import KeyStore +from aws_cryptographic_material_providers.keystore.config import KeyStoreConfig +from aws_cryptographic_material_providers.keystore.models import KMSConfigurationKmsKeyArn +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( AesWrappingAlg, CacheTypeDefault, CreateAwsKmsHierarchicalKeyringInput, @@ -21,7 +21,7 @@ DefaultCache, PaddingScheme, ) -from aws_cryptographic_materialproviders.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.references import IKeyring from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa diff --git a/test/unit/test_streaming_client_configs.py b/test/unit/test_streaming_client_configs.py index fc066ef1a..d0ecefcf4 100644 --- a/test/unit/test_streaming_client_configs.py +++ b/test/unit/test_streaming_client_configs.py @@ -23,7 +23,7 @@ # Ideally, this logic would be based on mocking imports and testing logic, # but doing that introduces errors that cause other tests to fail. try: - from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring + from aws_cryptographic_material_providers.mpl.references import ICryptographicMaterialsManager, IKeyring HAS_MPL = True from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL diff --git a/test/unit/test_streaming_client_mpl_import.py b/test/unit/test_streaming_client_mpl_import.py index 638b04fd6..0dcd8a981 100644 --- a/test/unit/test_streaming_client_mpl_import.py +++ b/test/unit/test_streaming_client_mpl_import.py @@ -13,7 +13,7 @@ # Ideally, this logic would be based on mocking imports and testing logic, # but doing that introduces errors that cause other tests to fail. try: - import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import + import aws_cryptographic_material_providers # noqa pylint: disable=unused-import HAS_MPL = True except ImportError: HAS_MPL = False diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt index 6cffc62e6..6995b3187 100644 --- a/test_vector_handlers/requirements_mpl.txt +++ b/test_vector_handlers/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptography-internal-mpl-testvectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-with-dafny-code#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptography-internal-mpl-testvectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py index d1e7a6811..91b68287a 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt.py @@ -6,7 +6,7 @@ from awses_test_vectors.manifests.full_message.decrypt import MessageDecryptionManifest try: - import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + import aws_cryptographic_material_providers # noqa pylint: disable=unused-import,import-error _HAS_MPL = True except ImportError: _HAS_MPL = False diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py index 49f2647fa..6383f7229 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_decrypt_generate.py @@ -6,7 +6,7 @@ from awses_test_vectors.manifests.full_message.decrypt_generation import MessageDecryptionGenerationManifest try: - import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + import aws_cryptographic_material_providers # noqa pylint: disable=unused-import,import-error _HAS_MPL = True except ImportError: _HAS_MPL = False diff --git a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py index ba7579e6f..1025b9426 100644 --- a/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/commands/full_message_encrypt.py @@ -6,7 +6,7 @@ from awses_test_vectors.manifests.full_message.encrypt import MessageEncryptionManifest try: - import aws_cryptographic_materialproviders # noqa pylint: disable=unused-import,import-error + import aws_cryptographic_material_providers # noqa pylint: disable=unused-import,import-error _HAS_MPL = True except ImportError: _HAS_MPL = False diff --git a/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py b/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py index 29a820ecc..00a0eb252 100644 --- a/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py +++ b/test_vector_handlers/src/awses_test_vectors/internal/mpl/tampering_mpl_materials.py @@ -16,9 +16,9 @@ from aws_encryption_sdk.materials_managers.mpl.cmm import ( CryptoMaterialsManagerFromMPL ) -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import ( +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.models import ( CreateDefaultCryptographicMaterialsManagerInput, ) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index 79df4f2cf..0f5b2e680 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -29,10 +29,10 @@ try: from awses_test_vectors.manifests.mpl_keyring import KeyringSpec, keyring_from_master_key_specs - from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager - from aws_cryptographic_materialproviders.mpl.models import ( + from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + from aws_cryptographic_material_providers.mpl.references import ICryptographicMaterialsManager + from aws_cryptographic_material_providers.mpl.models import ( CreateDefaultCryptographicMaterialsManagerInput, CreateRequiredEncryptionContextCMMInput, ) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py index 63f8b8ff3..2e94dc6a7 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt_generation.py @@ -19,12 +19,12 @@ from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager try: - from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders - from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig - from aws_cryptographic_materialproviders.mpl.references import ( + from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders + from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig + from aws_cryptographic_material_providers.mpl.references import ( IKeyring, ) - from aws_cryptographic_materialproviders.mpl.models import ( + from aws_cryptographic_material_providers.mpl.models import ( CreateDefaultCryptographicMaterialsManagerInput, ) from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py index 81581fa8e..2a6795902 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/encrypt.py @@ -33,7 +33,7 @@ from aws_encryption_sdk.identifiers import Algorithm as AlgorithmSuite try: - from aws_cryptographic_materialproviders.mpl.references import ( + from aws_cryptographic_material_providers.mpl.references import ( IKeyring, ) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index 7e64f9983..96af030d7 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -7,8 +7,9 @@ """ import attr import six +from aws_encryption_sdk.exceptions import InvalidKeyIdError from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm -from aws_encryption_sdk.key_providers.base import MasterKeyProvider # noqa pylint: disable=unused-import +from aws_encryption_sdk.key_providers.base import MasterKeyProvider, MasterKeyProviderConfig from aws_encryption_sdk.key_providers.kms import ( # noqa pylint: disable=unused-import DiscoveryFilter, KMSMasterKey, @@ -290,6 +291,44 @@ def scenario_spec(self): return spec +class TestVectorsMultiMasterKeyProvider(MasterKeyProvider): + """ + Provider for other MasterKeyProviders. + Acts as a "multi" MasterKeyProvider for use in test vectors. + + There is some disagreement between the spec + and how Python ESDK implements MasterKey; + this class fills that gap. + + In the ESDK-Python, MasterKey extends MasterKeyProvider; + i.e. MasterKey "is a" MasterKeyProvider; isinstance(some_master_key, MasterKeyProvider) == True. + + From AWS ESDK specification: + "A master key MUST supply itself and MUST NOT supply any other master keys." + https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/master-key-interface.md#get-master-key + + The MasterKey class overrides MasterKeyProvider's `decrypt_data_key` method to correct this gap. + However, this modification suggests that this "is a" relationship is not entirely true. + + master_key_provider_from_master_key_specs expects to return a MasterKeyProvider, not a MasterKey. + master_key_provider_from_master_key_specs uses this class to always return a MasterKeyProvider + that wraps any MasterKeyProvider or MasterKey loaded from a spec. + """ + + _config_class = MasterKeyProviderConfig + provider_id = "aws-test-vectors-multi-master-key-provider" + _members = [] + + def add_key(self, key_provider): + """Add a MKP to the list of configured MKPs.""" + self._members.append(key_provider) + + def _new_master_key(self, key_id): + # This MKP does not have a key associated with it. + # ESDK-Python will find keys in _members. + raise InvalidKeyIdError() + + def master_key_provider_from_master_key_specs(keys, master_key_specs): # type: (KeysManifest, Iterable[MasterKeySpec]) -> MasterKeyProvider """Build and combine all master key providers identified by the provided specs and @@ -312,8 +351,7 @@ def master_key_provider_from_master_key_specs(keys, master_key_specs): pass if len(master_keys) == 0: return None - primary = master_keys[0] - others = master_keys[1:] - for master_key in others: - primary.add_master_key_provider(master_key) - return primary + mkp = TestVectorsMultiMasterKeyProvider() + for master_key in master_keys: + mkp.add_key(master_key) + return mkp diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py index f2ea05559..8d972d2c5 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -25,10 +25,10 @@ GetKeyDescriptionOutput, TestVectorKeyringInput, ) -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.references import IKeyring -from aws_cryptographic_materialproviders.mpl.models import CreateMultiKeyringInput +from aws_cryptographic_material_providers.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_material_providers.mpl.config import MaterialProvidersConfig +from aws_cryptographic_material_providers.mpl.references import IKeyring +from aws_cryptographic_material_providers.mpl.models import CreateMultiKeyringInput import _dafny from smithy_dafny_standard_library.internaldafny.generated import UTF8 From c14f7fed96fdd3b9f5a7e2ed669d1eed3ecf67f0 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 24 Oct 2024 09:25:34 -0700 Subject: [PATCH 30/51] chore: Point at PyPI MPL (#709) --- README.rst | 2 +- performance_tests/README.rst | 2 +- performance_tests/requirements_mpl.txt | 2 +- requirements_mpl.txt | 2 +- setup.py | 4 +--- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 72d72cc26..5ff192733 100644 --- a/README.rst +++ b/README.rst @@ -42,7 +42,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: >= 1.8.0 (TODO-MPL: versionme) +* aws-cryptographic-material-providers: == 1.7.2 * Requires Python 3.11+. Installation diff --git a/performance_tests/README.rst b/performance_tests/README.rst index ba9b89f15..8ec315343 100644 --- a/performance_tests/README.rst +++ b/performance_tests/README.rst @@ -49,7 +49,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: >= 1.0.0 +* aws-cryptographic-material-providers: == 1.7.2 * Requires Python 3.11+. ***** diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index 9d72dfb8e..77c6460a5 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python +aws-cryptographic-material-providers==1.7.2 \ No newline at end of file diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 9d72dfb8e..58c7d2012 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python +aws-cryptographic-material-providers==1.7.2 diff --git a/setup.py b/setup.py index 6260c1ad2..dfbf91664 100644 --- a/setup.py +++ b/setup.py @@ -43,9 +43,7 @@ def get_requirements(): # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ - "MPL": ["aws-cryptographic-material-providers @" \ - "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ - "python-main-with-dafny-code#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + "MPL": ["aws-cryptographic-material-providers==1.7.2"], }, classifiers=[ "Development Status :: 5 - Production/Stable", From cb565041c9249af746d7e16ab15fd723d359d0f7 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 28 Oct 2024 10:28:09 -0700 Subject: [PATCH 31/51] chore(release): Bump ESDK version, add changelog (#710) --- CHANGELOG.rst | 27 +++++++++++++++++++++++++++ src/aws_encryption_sdk/identifiers.py | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 609b58c73..56cba75a2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,33 @@ Changelog ********* +4.0.0 -- 2024-10-29 +=================== + +Features +-------- +* Add support for constructs from the `AWS Cryptographic Material Providers Library (MPL) `_. + The MPL contains new constructs for encrypting and decrypting your data. + We highly recommend installing the MPL. See `Installing `_ for instructions. + +Breaking Changes +^^^^^^^^^^^^^^^^ +* The MPL introduces the Required Encryption Context Cryptographic Materials Manager + ("required EC CMM") as a new construct for protecting your data. + On encrypt, the required EC CMM will use specific configured + encryption context key-value pairs to calculate the message signature, + but will not store those pairs in the ESDK message. + On decrypt, decryptors must supply these same pairs that were used when encrypting the message. + All messages that have been encrypted with versions of the ESDK <4.0.0 are forward compatible with this change. + However, messages that are constructed with the required EC CMM are not backward compatible with ESDK <4.0.0, + as no version of ESDK <4.0.0 supports reading messages encrypted with the required EC CMM. + A message that is encrypted with the required EC CMM from the MPL must be decrypted with a CMM from the MPL. + +Fixes +----------- +* fix: MKPs attempt to decrypt with remaining keys if a preceding raw RSA key failed to decrypt + `#707 `_ + 3.3.0 -- 2024-05-20 =================== diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index a06030889..3e5a9940b 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -17,7 +17,7 @@ # We only actually need these imports when running the mypy checks pass -__version__ = "3.3.0" +__version__ = "4.0.0" USER_AGENT_SUFFIX = "AwsEncryptionSdkPython/{}".format(__version__) From 2bdd114479280f7ee30e10f532640a50286eb7a9 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 28 Oct 2024 14:59:49 -0700 Subject: [PATCH 32/51] chore(CI): Fix TestVectors timeout (#711) --- .../manifests/full_message/decrypt.py | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index 0f5b2e680..c942d8bf4 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -630,21 +630,11 @@ def from_file(cls, input_file, keyrings): client_name = raw_manifest["client"]["name"] # type: str client_version = raw_manifest["client"]["version"] # type: str raw_scenarios = raw_manifest["tests"] # type: Dict[str, DECRYPT_SCENARIO_SPEC] - test_scenarios = { - name: MessageDecryptionTestScenario.from_scenario( - scenario=scenario, - plaintext_reader=root_reader, - ciphertext_reader=root_reader, - keys=keys, - keyrings=False, - keys_uri=keys_abs_path, - ) - for name, scenario in raw_scenarios.items() - } - # If optional keyrings argument is true, - # also add scenarios to decrypt with keyrings. + + # If optional keyrings argument is specified, + # decrypt with keyrings if keyrings: - keyrings_test_scenarios = { + test_scenarios = { name + "-keyring": MessageDecryptionTestScenario.from_scenario( scenario=scenario, plaintext_reader=root_reader, @@ -655,8 +645,20 @@ def from_file(cls, input_file, keyrings): ) for name, scenario in raw_scenarios.items() } - # Merge keyring scenarios into test_scenarios - test_scenarios = {**keyrings_test_scenarios, **test_scenarios} + # If optional keyrings argument is not specified, + # decrypt with master key providers. + else: + test_scenarios = { + name: MessageDecryptionTestScenario.from_scenario( + scenario=scenario, + plaintext_reader=root_reader, + ciphertext_reader=root_reader, + keys=keys, + keyrings=False, + keys_uri=keys_abs_path, + ) + for name, scenario in raw_scenarios.items() + } # Remove any `None` scenarios from test scenarios. # `None` scenarios indicate the loader determined the scenario is invalid. From 8383b064f54e799245844d443ae07fcdb01cfe6f Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 29 Oct 2024 13:38:56 -0700 Subject: [PATCH 33/51] Update src/aws_encryption_sdk/internal/formatting/deserialize.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Corella <39066999+josecorella@users.noreply.github.com> --- src/aws_encryption_sdk/internal/formatting/deserialize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/internal/formatting/deserialize.py b/src/aws_encryption_sdk/internal/formatting/deserialize.py index 22cb84a30..4511ebb69 100644 --- a/src/aws_encryption_sdk/internal/formatting/deserialize.py +++ b/src/aws_encryption_sdk/internal/formatting/deserialize.py @@ -467,7 +467,7 @@ def deserialize_frame(stream, header, verifier=None): (content_length,) = unpack_values(">I", stream, verifier) if content_length > header.frame_length: raise SerializationError( - "Invalid final frame length: {final} >= {normal}".format( + "Invalid final frame length: {final} > {normal}".format( final=content_length, normal=header.frame_length ) ) From 9cddd41de83044e1c3a3f911d6c34d2c37e39757 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 30 Oct 2024 15:50:11 -0700 Subject: [PATCH 34/51] feat(TestVectors): Decrypt "golden" manifest (#721) --- buildspec.yml | 16 ++++++++++ .../decrypt_golden_manifest_with_keyrings.yml | 31 +++++++++++++++++++ ...decrypt_golden_manifest_with_masterkey.yml | 30 ++++++++++++++++++ .../decrypt_golden_manifest_with_keyrings.yml | 31 +++++++++++++++++++ ...decrypt_golden_manifest_with_masterkey.yml | 30 ++++++++++++++++++ .../manifests/full_message/decrypt.py | 19 +++++++----- .../manifests/mpl_keyring.py | 11 ++++++- 7 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 codebuild/py311/decrypt_golden_manifest_with_keyrings.yml create mode 100644 codebuild/py311/decrypt_golden_manifest_with_masterkey.yml create mode 100644 codebuild/py312/decrypt_golden_manifest_with_keyrings.yml create mode 100644 codebuild/py312/decrypt_golden_manifest_with_masterkey.yml diff --git a/buildspec.yml b/buildspec.yml index 4665ac89e..4065dc4e8 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -206,6 +206,14 @@ batch: buildspec: codebuild/py311/decrypt_keyrings_with_js.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_golden_manifest_with_keyrings + buildspec: codebuild/py311/decrypt_golden_manifest_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py311_decrypt_golden_manifest_with_masterkey + buildspec: codebuild/py311/decrypt_golden_manifest_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_integ @@ -318,6 +326,14 @@ batch: buildspec: codebuild/py312/decrypt_hkeyring_with_net.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_golden_manifest_with_keyrings + buildspec: codebuild/py312/decrypt_golden_manifest_with_keyrings.yml + env: + image: aws/codebuild/standard:7.0 + - identifier: py312_decrypt_golden_manifest_with_masterkey + buildspec: codebuild/py312/decrypt_golden_manifest_with_masterkey.yml + env: + image: aws/codebuild/standard:7.0 - identifier: code_coverage buildspec: codebuild/coverage/coverage.yml diff --git a/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml new file mode 100644 index 000000000..154863bcc --- /dev/null +++ b/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download "golden manifest" + - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip + - unzip python-2.3.0.zip -d python-2.3.0 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../python-2.3.0/manifest.json \ + --keyrings diff --git a/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml b/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml new file mode 100644 index 000000000..4ae4bb280 --- /dev/null +++ b/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py311-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + pre_build: + commands: + # Download "golden manifest" + - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip + - unzip python-2.3.0.zip -d python-2.3.0 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../python-2.3.0/manifest.json diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml new file mode 100644 index 000000000..54bb10c33 --- /dev/null +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -0,0 +1,31 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download "golden manifest" + - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip + - unzip python-2.3.0.zip -d python-2.3.0 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../python-2.3.0/manifest.json \ + --keyrings diff --git a/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml b/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml new file mode 100644 index 000000000..df204d4c5 --- /dev/null +++ b/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + variables: + TOXENV: "py312-full_decrypt-mpl" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + pre_build: + commands: + # Download "golden manifest" + - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip + - unzip python-2.3.0.zip -d python-2.3.0 + build: + commands: + - pip install "tox < 4.0" + - cd test_vector_handlers + - | + tox -- \ + --input ../python-2.3.0/manifest.json diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py index c942d8bf4..a938106bd 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/full_message/decrypt.py @@ -264,7 +264,7 @@ def __init__( attr.validate(self) @classmethod - def from_scenario( + def from_scenario( # noqa: C901 cls, scenario, # type: DECRYPT_SCENARIO_SPEC plaintext_reader, # type: Callable[[str], bytes] @@ -273,7 +273,7 @@ def from_scenario( keyrings, # type: bool keys_uri, # type: str ): - # pylint: disable=too-many-locals + # pylint: disable=too-many-locals,too-many-branches # type: (...) -> MessageDecryptionTestScenario """Load from a scenario specification. @@ -330,11 +330,16 @@ def master_key_provider_fn(): # If unspecified, set "Default" as the default cmm_type = "Default" - # If this scenario does not have any key providers, - # do not create a scenario. - # Caller logic should expect `None` to mean "no scenario". - if master_key_provider_fn() is None: - return None + try: + # If this scenario does not have any key providers, + # do not create a scenario. + # Caller logic should expect `None` to mean "no scenario". + if master_key_provider_fn() is None: + return None + except Exception: # nosec,pylint: disable=broad-except + # If there is any exception when loading the key, continue to create the test scenario. + # Some test scenarios have bad keys that should fail during the test execution. + pass return cls( ciphertext_uri=scenario["ciphertext"], diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py index 8d972d2c5..3ed7913d2 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/mpl_keyring.py @@ -90,7 +90,8 @@ def from_scenario(cls, spec): padding_hash=spec.get("padding-hash"), ) - def keyring(self, keys_uri, mode): + def keyring(self, keys_uri, mode): # noqa: C901 + # pylint: disable=too-many-branches # type: (KeysManifest) -> IKeyring """Build a keyring using this specification. :param str keys_uri: Path to the keys manifest @@ -113,6 +114,14 @@ def keyring(self, keys_uri, mode): input_kwargs["padding-algorithm"] = self.padding_algorithm if self.padding_hash is not None: input_kwargs["padding-hash"] = self.padding_hash + if self.default_mrk_region is not None: + input_kwargs["default-mrk-region"] = self.default_mrk_region + if self.discovery_filter is not None: + input_kwargs["aws-kms-discovery-filter"] = {} + if self.discovery_filter.partition is not None: + input_kwargs["aws-kms-discovery-filter"]["partition"] = self.discovery_filter.partition + if self.discovery_filter.account_ids is not None: + input_kwargs["aws-kms-discovery-filter"]["account-ids"] = self.discovery_filter.account_ids if input_kwargs["type"] == "raw" \ and input_kwargs["encryption-algorithm"] == "rsa": From abfca2283b172f16ceac6b4e83f81a62e70baa5a Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 4 Nov 2024 12:04:56 -0800 Subject: [PATCH 35/51] chore(CI): Bump from macOS 12 to 13 (#723) --- .github/workflows/ci_test-vector-handler.yaml | 4 ++-- .github/workflows/ci_tests.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci_test-vector-handler.yaml b/.github/workflows/ci_test-vector-handler.yaml index 8a142096d..90c87e502 100644 --- a/.github/workflows/ci_test-vector-handler.yaml +++ b/.github/workflows/ci_test-vector-handler.yaml @@ -19,7 +19,7 @@ jobs: os: - ubuntu-latest - windows-latest - - macos-12 + - macos-13 python: - 3.8 - 3.x @@ -34,7 +34,7 @@ jobs: # x86 builds are only meaningful for Windows - os: ubuntu-latest architecture: x86 - - os: macos-12 + - os: macos-13 architecture: x86 steps: - uses: aws-actions/configure-aws-credentials@v4 diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index 1a3229683..256e49ce4 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -26,7 +26,7 @@ jobs: os: - ubuntu-latest - windows-latest - - macos-12 + - macos-13 python: - 3.8 - 3.9 @@ -54,7 +54,7 @@ jobs: # x86 builds are only meaningful for Windows - os: ubuntu-latest architecture: x86 - - os: macos-12 + - os: macos-13 architecture: x86 # MPL is not supported on <3.11 - python: 3.7 From 81d6766558d2da3787420d4645c955b5db23fde6 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 12:58:48 -0800 Subject: [PATCH 36/51] m --- .../decrypt_dafny_esdk_vectors_keyrings.yml | 2 ++ .../decrypt_golden_manifest_with_keyrings.yml | 2 ++ test_vector_handlers/requirements_mpl.txt | 2 +- test_vector_handlers/tox.ini | 23 +++++++++++++++---- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index 810d16b74..279056695 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -22,6 +22,8 @@ phases: python: 3.12 pre_build: commands: + # Build and install MPL test vector Python package + - tox -e install-mpl-runner # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) - | diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml index 54bb10c33..bf309a9a7 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -21,6 +21,8 @@ phases: # Download "golden manifest" - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip - unzip python-2.3.0.zip -d python-2.3.0 + # Build and install MPL test vector Python package + - tox -e install-mpl-runner build: commands: - pip install "tox < 4.0" diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt index 6995b3187..58c7d2012 100644 --- a/test_vector_handlers/requirements_mpl.txt +++ b/test_vector_handlers/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptography-internal-mpl-testvectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@python-main-with-dafny-code#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-material-providers==1.7.2 diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index cdb1137fb..44f34703a 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -38,6 +38,21 @@ envlist = [testenv:base-command] commands = pytest --basetemp={envtmpdir} -l --cov awses_test_vectors test/ --ignore test/mpl {posargs} +[testenv:install-mpl-runner] +commands = + # Clone MPL repo to get test vectors runner source code and the Dafny version to use + ; git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git + # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file + ; /bin/bash -c "export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)" + ; /bin/bash -c "curl https://github.com/dafny-lang/dafny/releases/download/v$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)/dafny-$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)-x64-ubuntu-20.04.zip -L -o dafny.zip" + ; /bin/bash -c "unzip -qq dafny.zip && rm dafny.zip" + ; /bin/bash -c 'export PATH="$PWD/dafny:$PATH"' + + # Build MPL test vector runner from source + make -C aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ transpile_python + # Install just the test vector runner, not its local MPL dependency + pip install aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/runtimes/python --no-deps + [testenv] passenv = # Pass through AWS credentials @@ -48,10 +63,10 @@ passenv = AWS_PROFILE sitepackages = False deps = - -rtest/requirements.txt - # Install the MPL requirements if the `-mpl` suffix is present - mpl: -rrequirements_mpl.txt - .. + ; -rtest/requirements.txt + ; # Install the MPL requirements if the `-mpl` suffix is present + ; mpl: -rrequirements_mpl.txt + ; .. commands = awses_local: {[testenv:base-command]commands} full_decrypt_generate: awses-full-message-decrypt-generate {posargs} From bf0b10853b7836c3bd892726d95df53ede77e666 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 12:59:05 -0800 Subject: [PATCH 37/51] m --- test_vector_handlers/tox.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index 44f34703a..8d66285e7 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -41,12 +41,12 @@ commands = pytest --basetemp={envtmpdir} -l --cov awses_test_vectors test/ --ign [testenv:install-mpl-runner] commands = # Clone MPL repo to get test vectors runner source code and the Dafny version to use - ; git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git + git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file - ; /bin/bash -c "export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)" - ; /bin/bash -c "curl https://github.com/dafny-lang/dafny/releases/download/v$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)/dafny-$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)-x64-ubuntu-20.04.zip -L -o dafny.zip" - ; /bin/bash -c "unzip -qq dafny.zip && rm dafny.zip" - ; /bin/bash -c 'export PATH="$PWD/dafny:$PATH"' + /bin/bash -c "export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)" + /bin/bash -c "curl https://github.com/dafny-lang/dafny/releases/download/v$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)/dafny-$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)-x64-ubuntu-20.04.zip -L -o dafny.zip" + /bin/bash -c "unzip -qq dafny.zip && rm dafny.zip" + /bin/bash -c 'export PATH="$PWD/dafny:$PATH"' # Build MPL test vector runner from source make -C aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ transpile_python From ae726937b280f445a8db9dbd9dacb45bbdb6a552 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 13:51:38 -0800 Subject: [PATCH 38/51] m --- codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index 279056695..6efa40491 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -23,6 +23,7 @@ phases: pre_build: commands: # Build and install MPL test vector Python package + - pip install "tox < 4.0" - tox -e install-mpl-runner # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) @@ -53,7 +54,6 @@ phases: - unzip net41.zip -d net41 build: commands: - - pip install "tox < 4.0" - cd test_vector_handlers - | tox -- \ From e9085b760edb47b24af6d8693cbefd6aea99d18a Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 13:58:03 -0800 Subject: [PATCH 39/51] m --- codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index 6efa40491..e2c61fd3a 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -24,7 +24,9 @@ phases: commands: # Build and install MPL test vector Python package - pip install "tox < 4.0" + - cd test_vector_handlers/ - tox -e install-mpl-runner + - cd .. # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) - | From 2e369a30387ef4becc41a5b577c0d5d2abf88e71 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:01:51 -0800 Subject: [PATCH 40/51] no tox --- .../decrypt_dafny_esdk_vectors_keyrings.yml | 22 ++++++++++++++----- .../decrypt_golden_manifest_with_keyrings.yml | 20 +++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index e2c61fd3a..b2840d051 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -22,11 +22,23 @@ phases: python: 3.12 pre_build: commands: - # Build and install MPL test vector Python package - - pip install "tox < 4.0" - - cd test_vector_handlers/ - - tox -e install-mpl-runner - - cd .. + # Build Python MPL TestVector runner from source + # Clone MPL repo to get test vectors runner source code and the Dafny version to use + - git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git + # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file + - export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) + - curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip + - unzip -qq dafny.zip && rm dafny.zip + - export PATH="$PWD/dafny:$PATH" + + # Build MPL test vector runner from source + - cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ + - make transpile_python + # Install built runner. + # (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) + - pip install runtimes/python --no-deps + - cd ../../ + # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) - | diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml index bf309a9a7..3cfc2ffe8 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -21,8 +21,24 @@ phases: # Download "golden manifest" - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip - unzip python-2.3.0.zip -d python-2.3.0 - # Build and install MPL test vector Python package - - tox -e install-mpl-runner + + # Build Python MPL TestVector runner from source + # Clone MPL repo to get test vectors runner source code and the Dafny version to use + - git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git + # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file + - export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) + - curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip + - unzip -qq dafny.zip && rm dafny.zip + - export PATH="$PWD/dafny:$PATH" + + # Build MPL test vector runner from source + - cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ + - make transpile_python + # Install built runner. + # (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) + - pip install runtimes/python --no-deps + - cd ../../ + build: commands: - pip install "tox < 4.0" From 567533c2d99d06cd76d6053fe3bdeb8f868fdf9a Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:06:43 -0800 Subject: [PATCH 41/51] no tox --- codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index b2840d051..e06a77f3e 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -68,6 +68,7 @@ phases: - unzip net41.zip -d net41 build: commands: + - pip install "tox < 4.0" - cd test_vector_handlers - | tox -- \ From fa28345d57fb04c24bb4b549ace8f7206678f463 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:10:20 -0800 Subject: [PATCH 42/51] no tox --- test_vector_handlers/tox.ini | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index 8d66285e7..cdb1137fb 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -38,21 +38,6 @@ envlist = [testenv:base-command] commands = pytest --basetemp={envtmpdir} -l --cov awses_test_vectors test/ --ignore test/mpl {posargs} -[testenv:install-mpl-runner] -commands = - # Clone MPL repo to get test vectors runner source code and the Dafny version to use - git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git - # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file - /bin/bash -c "export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)" - /bin/bash -c "curl https://github.com/dafny-lang/dafny/releases/download/v$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)/dafny-$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2)-x64-ubuntu-20.04.zip -L -o dafny.zip" - /bin/bash -c "unzip -qq dafny.zip && rm dafny.zip" - /bin/bash -c 'export PATH="$PWD/dafny:$PATH"' - - # Build MPL test vector runner from source - make -C aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ transpile_python - # Install just the test vector runner, not its local MPL dependency - pip install aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/runtimes/python --no-deps - [testenv] passenv = # Pass through AWS credentials @@ -63,10 +48,10 @@ passenv = AWS_PROFILE sitepackages = False deps = - ; -rtest/requirements.txt - ; # Install the MPL requirements if the `-mpl` suffix is present - ; mpl: -rrequirements_mpl.txt - ; .. + -rtest/requirements.txt + # Install the MPL requirements if the `-mpl` suffix is present + mpl: -rrequirements_mpl.txt + .. commands = awses_local: {[testenv:base-command]commands} full_decrypt_generate: awses-full-message-decrypt-generate {posargs} From bb0e64e1175b9399cd49464a5d705e661aae1ca9 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:12:47 -0800 Subject: [PATCH 43/51] m --- .../decrypt_dafny_esdk_vectors_keyrings.yml | 16 +--------------- .../decrypt_golden_manifest_with_keyrings.yml | 16 +--------------- .../scripts/install_mpl_test_vector_runner.sh | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 30 deletions(-) create mode 100644 test_vector_handlers/scripts/install_mpl_test_vector_runner.sh diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index e06a77f3e..a3bac8e27 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -23,21 +23,7 @@ phases: pre_build: commands: # Build Python MPL TestVector runner from source - # Clone MPL repo to get test vectors runner source code and the Dafny version to use - - git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git - # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file - - export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) - - curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip - - unzip -qq dafny.zip && rm dafny.zip - - export PATH="$PWD/dafny:$PATH" - - # Build MPL test vector runner from source - - cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ - - make transpile_python - # Install built runner. - # (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) - - pip install runtimes/python --no-deps - - cd ../../ + - sh scripts/install_mpl_test_vector_runner.sh # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml index 3cfc2ffe8..c0ca51cb6 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -23,21 +23,7 @@ phases: - unzip python-2.3.0.zip -d python-2.3.0 # Build Python MPL TestVector runner from source - # Clone MPL repo to get test vectors runner source code and the Dafny version to use - - git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git - # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file - - export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) - - curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip - - unzip -qq dafny.zip && rm dafny.zip - - export PATH="$PWD/dafny:$PATH" - - # Build MPL test vector runner from source - - cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ - - make transpile_python - # Install built runner. - # (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) - - pip install runtimes/python --no-deps - - cd ../../ + - sh scripts/install_mpl_test_vector_runner.sh build: commands: diff --git a/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh new file mode 100644 index 000000000..fbd8d1159 --- /dev/null +++ b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh @@ -0,0 +1,16 @@ +# Build Python MPL TestVector runner from source +# Clone MPL repo to get test vectors runner source code and the Dafny version to use +git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git +# Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file +export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) +curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip +unzip -qq dafny.zip && rm dafny.zip +export PATH="$PWD/dafny:$PATH" + +# Build MPL test vector runner from source +cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ +make transpile_python +# Install built runner. +# (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) +pip install runtimes/python --no-deps +cd ../../ From 234b9a6e4ceb49863f713fb915c43d00f29b23d3 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:15:38 -0800 Subject: [PATCH 44/51] m --- codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml | 2 +- codebuild/py312/decrypt_golden_manifest_with_keyrings.yml | 2 +- .../scripts/install_mpl_test_vector_runner.sh | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index a3bac8e27..00a7526ff 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -23,7 +23,7 @@ phases: pre_build: commands: # Build Python MPL TestVector runner from source - - sh scripts/install_mpl_test_vector_runner.sh + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml index c0ca51cb6..9b68b1122 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -23,7 +23,7 @@ phases: - unzip python-2.3.0.zip -d python-2.3.0 # Build Python MPL TestVector runner from source - - sh scripts/install_mpl_test_vector_runner.sh + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh build: commands: diff --git a/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh index fbd8d1159..f213dc10d 100644 --- a/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh +++ b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh @@ -1,4 +1,9 @@ -# Build Python MPL TestVector runner from source +# Builds the Python MPL TestVector runner from source. +# This package is used by the ESDK-Python test vectors for testing with the MPL. + +# This script is intended to be used by ESDK-Python's integration tests. +# You may need or want to make local changes to get this work on your machine. + # Clone MPL repo to get test vectors runner source code and the Dafny version to use git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file @@ -6,7 +11,6 @@ export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip unzip -qq dafny.zip && rm dafny.zip export PATH="$PWD/dafny:$PATH" - # Build MPL test vector runner from source cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ make transpile_python From 3653a2bc8b672c7cec60ab3d336abdff9e988b52 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 14:55:35 -0800 Subject: [PATCH 45/51] m --- requirements_mpl.txt | 2 +- .../scripts/install_mpl_test_vector_runner.sh | 14 +++++++++----- test_vector_handlers/tox.ini | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 58c7d2012..4cee96294 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers==1.7.2 +aws-cryptographic-material-providers==1.7.3 diff --git a/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh index f213dc10d..b99226e66 100644 --- a/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh +++ b/test_vector_handlers/scripts/install_mpl_test_vector_runner.sh @@ -4,17 +4,21 @@ # This script is intended to be used by ESDK-Python's integration tests. # You may need or want to make local changes to get this work on your machine. +# Change to the directory of the script +cd "$(dirname "$0")" + +# Get MPL version specified in requirements.txt +export mplVersion=$(grep 'aws-cryptographic-material-providers==' ../requirements_mpl.txt | sed -E 's/.*==(.+)/\1/') + # Clone MPL repo to get test vectors runner source code and the Dafny version to use -git clone --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git +git clone --branch v$mplVersion --recurse-submodules https://github.com/aws/aws-cryptographic-material-providers-library.git + # Download Dafny to build the test vector runner; get Dafny version from ESDK's project.properties file export dafnyVersion=$(grep '^dafnyVersion=' aws-cryptographic-material-providers-library/project.properties | cut -d '=' -f 2) curl https://github.com/dafny-lang/dafny/releases/download/v$dafnyVersion/dafny-$dafnyVersion-x64-ubuntu-20.04.zip -L -o dafny.zip unzip -qq dafny.zip && rm dafny.zip export PATH="$PWD/dafny:$PATH" + # Build MPL test vector runner from source cd aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/ make transpile_python -# Install built runner. -# (no-deps skips installing its local MPL dependency in favor of the one from PyPI.) -pip install runtimes/python --no-deps -cd ../../ diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index cdb1137fb..7fe77ff50 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -51,6 +51,9 @@ deps = -rtest/requirements.txt # Install the MPL requirements if the `-mpl` suffix is present mpl: -rrequirements_mpl.txt + # This is the filepath used in ESDK-Python's integration tests. + # You may need to change this to run this project locally. + mpl: scripts/aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/runtimes/python .. commands = awses_local: {[testenv:base-command]commands} From bec81a520e94b740d8c9d0e22358271501a12679 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 5 Nov 2024 15:23:16 -0800 Subject: [PATCH 46/51] spread --- codebuild/py311/awses_local_mpl.yml | 2 ++ codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml | 2 ++ codebuild/py311/decrypt_golden_manifest_with_keyrings.yml | 2 ++ codebuild/py311/decrypt_golden_manifest_with_masterkey.yml | 2 +- codebuild/py311/decrypt_keyrings_with_keyrings.yml | 2 ++ codebuild/py311/decrypt_masterkey_with_keyrings.yml | 2 ++ codebuild/py311/decrypt_net_401_vectors_keyrings.yml | 2 ++ codebuild/py311/encrypt_keyrings.yml | 2 ++ codebuild/py311/generate_decrypt_vectors_keyrings.yml | 2 ++ codebuild/py312/awses_local_mpl.yml | 2 ++ codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml | 1 - codebuild/py312/decrypt_golden_manifest_with_keyrings.yml | 6 ++---- codebuild/py312/decrypt_golden_manifest_with_masterkey.yml | 2 +- codebuild/py312/decrypt_hkeyring_with_keyrings.yml | 2 ++ codebuild/py312/decrypt_hkeyring_with_masterkey.yml | 2 +- codebuild/py312/decrypt_keyrings_with_keyrings.yml | 2 ++ codebuild/py312/decrypt_masterkey_with_keyrings.yml | 2 ++ codebuild/py312/decrypt_net_401_vectors_keyrings.yml | 2 ++ codebuild/py312/encrypt_keyrings.yml | 2 ++ codebuild/py312/generate_decrypt_vectors_keyrings.yml | 2 ++ codebuild/py312/generate_hkeyring_decrypt_vectors.yml | 2 ++ 21 files changed, 37 insertions(+), 8 deletions(-) diff --git a/codebuild/py311/awses_local_mpl.yml b/codebuild/py311/awses_local_mpl.yml index 859931aa3..c6a975df8 100644 --- a/codebuild/py311/awses_local_mpl.yml +++ b/codebuild/py311/awses_local_mpl.yml @@ -21,6 +21,8 @@ phases: python: 3.11 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers - tox diff --git a/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml index d69ce9370..1eadf2958 100644 --- a/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py311/decrypt_dafny_esdk_vectors_keyrings.yml @@ -22,6 +22,8 @@ phases: python: 3.11 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) - | diff --git a/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml index 154863bcc..c65816d69 100644 --- a/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py311/decrypt_golden_manifest_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.11 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download "golden manifest" - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip - unzip python-2.3.0.zip -d python-2.3.0 diff --git a/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml b/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml index 4ae4bb280..3b71759d3 100644 --- a/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml +++ b/codebuild/py311/decrypt_golden_manifest_with_masterkey.yml @@ -2,7 +2,7 @@ version: 0.2 env: variables: - TOXENV: "py311-full_decrypt-mpl" + TOXENV: "py311-full_decrypt" AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- diff --git a/codebuild/py311/decrypt_keyrings_with_keyrings.yml b/codebuild/py311/decrypt_keyrings_with_keyrings.yml index fec275d48..f202c9c69 100644 --- a/codebuild/py311/decrypt_keyrings_with_keyrings.yml +++ b/codebuild/py311/decrypt_keyrings_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.11 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download previously generated vectors - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_keyrings.zip 311_keyrings.zip - unzip 311_keyrings.zip diff --git a/codebuild/py311/decrypt_masterkey_with_keyrings.yml b/codebuild/py311/decrypt_masterkey_with_keyrings.yml index 8543077bd..1542b1acb 100644 --- a/codebuild/py311/decrypt_masterkey_with_keyrings.yml +++ b/codebuild/py311/decrypt_masterkey_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.11 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download previously generated vectors - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/311_masterkey.zip 311_masterkey.zip - unzip 311_masterkey.zip diff --git a/codebuild/py311/decrypt_net_401_vectors_keyrings.yml b/codebuild/py311/decrypt_net_401_vectors_keyrings.yml index 1a23f0917..b5e7d7233 100644 --- a/codebuild/py311/decrypt_net_401_vectors_keyrings.yml +++ b/codebuild/py311/decrypt_net_401_vectors_keyrings.yml @@ -19,6 +19,8 @@ phases: python: 3.11 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Fetch ESDK .NET v4.0.1 Test Vectors - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip diff --git a/codebuild/py311/encrypt_keyrings.yml b/codebuild/py311/encrypt_keyrings.yml index 8b7cb94b4..8e315ca9f 100644 --- a/codebuild/py311/encrypt_keyrings.yml +++ b/codebuild/py311/encrypt_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.11 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers - | diff --git a/codebuild/py311/generate_decrypt_vectors_keyrings.yml b/codebuild/py311/generate_decrypt_vectors_keyrings.yml index 179ec0f12..0c9fc8333 100644 --- a/codebuild/py311/generate_decrypt_vectors_keyrings.yml +++ b/codebuild/py311/generate_decrypt_vectors_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.11 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers - | diff --git a/codebuild/py312/awses_local_mpl.yml b/codebuild/py312/awses_local_mpl.yml index c92265541..ea4d4f229 100644 --- a/codebuild/py312/awses_local_mpl.yml +++ b/codebuild/py312/awses_local_mpl.yml @@ -23,6 +23,8 @@ phases: python: 3.12 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - - pyenv install --skip-existing 3.12.0 - pyenv local 3.12.0 diff --git a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml index 00a7526ff..2a8439253 100644 --- a/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_dafny_esdk_vectors_keyrings.yml @@ -24,7 +24,6 @@ phases: commands: # Build Python MPL TestVector runner from source - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - # Fetch test vectors from Dafny ESDK's most recent run # (Assuming the first result is most recent; seems to be correct...) - | diff --git a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml index 9b68b1122..c0442a10b 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_keyrings.yml @@ -18,13 +18,11 @@ phases: python: 3.12 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download "golden manifest" - curl -L -o python-2.3.0.zip https://github.com/awslabs/aws-encryption-sdk-test-vectors/raw/master/vectors/awses-decrypt/python-2.3.0.zip - unzip python-2.3.0.zip -d python-2.3.0 - - # Build Python MPL TestVector runner from source - - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - build: commands: - pip install "tox < 4.0" diff --git a/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml b/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml index df204d4c5..0e2ecb287 100644 --- a/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml +++ b/codebuild/py312/decrypt_golden_manifest_with_masterkey.yml @@ -2,7 +2,7 @@ version: 0.2 env: variables: - TOXENV: "py312-full_decrypt-mpl" + TOXENV: "py312-full_decrypt" AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- diff --git a/codebuild/py312/decrypt_hkeyring_with_keyrings.yml b/codebuild/py312/decrypt_hkeyring_with_keyrings.yml index 5bcd26738..844f4c464 100644 --- a/codebuild/py312/decrypt_hkeyring_with_keyrings.yml +++ b/codebuild/py312/decrypt_hkeyring_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.12 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download previously generated vectors # This manifest has coverage for both HKeyring and required encryption context CMM - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_hkeyring_reccmm_manifest.zip 312_hkeyring_reccmm_manifest.zip diff --git a/codebuild/py312/decrypt_hkeyring_with_masterkey.yml b/codebuild/py312/decrypt_hkeyring_with_masterkey.yml index be67235d7..04def1a98 100644 --- a/codebuild/py312/decrypt_hkeyring_with_masterkey.yml +++ b/codebuild/py312/decrypt_hkeyring_with_masterkey.yml @@ -2,7 +2,7 @@ version: 0.2 env: variables: - TOXENV: "py312-full_decrypt-mpl" + TOXENV: "py312-full_decrypt" AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- arn:aws:kms:us-west-2:658956600833:key/b35311ef1-d8dc-4780-9f5a-55776cbb2f7f AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- diff --git a/codebuild/py312/decrypt_keyrings_with_keyrings.yml b/codebuild/py312/decrypt_keyrings_with_keyrings.yml index 3ab7058f9..27f9f1b5e 100644 --- a/codebuild/py312/decrypt_keyrings_with_keyrings.yml +++ b/codebuild/py312/decrypt_keyrings_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.12 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download previously generated vectors - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_keyrings.zip 312_keyrings.zip - unzip 312_keyrings.zip diff --git a/codebuild/py312/decrypt_masterkey_with_keyrings.yml b/codebuild/py312/decrypt_masterkey_with_keyrings.yml index 21f646370..e22bd2ace 100644 --- a/codebuild/py312/decrypt_masterkey_with_keyrings.yml +++ b/codebuild/py312/decrypt_masterkey_with_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.12 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Download previously generated vectors - aws s3 cp s3://generated-vectors-artifacts-bucket/$CODEBUILD_RESOLVED_SOURCE_VERSION/312_masterkey.zip 312_masterkey.zip - unzip 312_masterkey.zip diff --git a/codebuild/py312/decrypt_net_401_vectors_keyrings.yml b/codebuild/py312/decrypt_net_401_vectors_keyrings.yml index aec3916e5..3156e06ab 100644 --- a/codebuild/py312/decrypt_net_401_vectors_keyrings.yml +++ b/codebuild/py312/decrypt_net_401_vectors_keyrings.yml @@ -19,6 +19,8 @@ phases: python: 3.12 pre_build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh # Fetch ESDK .NET v4.0.1 Test Vectors - VECTOR_ZIP=$CODEBUILD_SRC_DIR/v4-Net-4.0.1.zip - VECTORS_URL=https://github.com/aws/aws-encryption-sdk-dafny/raw/mainline/AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectors/resources/v4-Net-4.0.1.zip diff --git a/codebuild/py312/encrypt_keyrings.yml b/codebuild/py312/encrypt_keyrings.yml index 56a389e6f..db12d6c9d 100644 --- a/codebuild/py312/encrypt_keyrings.yml +++ b/codebuild/py312/encrypt_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.12 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers - | diff --git a/codebuild/py312/generate_decrypt_vectors_keyrings.yml b/codebuild/py312/generate_decrypt_vectors_keyrings.yml index ae79b86ce..1760333f0 100644 --- a/codebuild/py312/generate_decrypt_vectors_keyrings.yml +++ b/codebuild/py312/generate_decrypt_vectors_keyrings.yml @@ -18,6 +18,8 @@ phases: python: 3.12 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers - | diff --git a/codebuild/py312/generate_hkeyring_decrypt_vectors.yml b/codebuild/py312/generate_hkeyring_decrypt_vectors.yml index b0a755360..15b4f485e 100644 --- a/codebuild/py312/generate_hkeyring_decrypt_vectors.yml +++ b/codebuild/py312/generate_hkeyring_decrypt_vectors.yml @@ -18,6 +18,8 @@ phases: python: 3.12 build: commands: + # Build Python MPL TestVector runner from source + - sh test_vector_handlers/scripts/install_mpl_test_vector_runner.sh - pip install "tox < 4.0" - cd test_vector_handlers/test/aws-crypto-tools-test-vector-framework # Checkout WIP branch with manifest containing HKeyring and required EC CMM test cases From 06cd362b68d68d0ea2db8d6a7f3a660ca618db25 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 11 Nov 2024 14:49:45 -0800 Subject: [PATCH 47/51] chore: Bump to MPL 1.7.4 --- README.rst | 2 +- performance_tests/README.rst | 2 +- performance_tests/requirements_mpl.txt | 2 +- requirements_mpl.txt | 2 +- setup.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 5ff192733..b968ae13e 100644 --- a/README.rst +++ b/README.rst @@ -42,7 +42,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: == 1.7.2 +* aws-cryptographic-material-providers: == 1.7.4 * Requires Python 3.11+. Installation diff --git a/performance_tests/README.rst b/performance_tests/README.rst index 8ec315343..ee3dd797b 100644 --- a/performance_tests/README.rst +++ b/performance_tests/README.rst @@ -49,7 +49,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: == 1.7.2 +* aws-cryptographic-material-providers: == 1.7.4 * Requires Python 3.11+. ***** diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index 77c6460a5..1615fff0d 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers==1.7.2 \ No newline at end of file +aws-cryptographic-material-providers==1.7.4 \ No newline at end of file diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 58c7d2012..f1a309033 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers==1.7.2 +aws-cryptographic-material-providers==1.7.4 diff --git a/setup.py b/setup.py index dfbf91664..ab5ac71a3 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def get_requirements(): # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ - "MPL": ["aws-cryptographic-material-providers==1.7.2"], + "MPL": ["aws-cryptographic-material-providers==1.7.4"], }, classifiers=[ "Development Status :: 5 - Production/Stable", From dcf2de752ae02f3e1870dc280975ba94b972d813 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 11 Nov 2024 15:45:33 -0800 Subject: [PATCH 48/51] chore: Bump to MPL 1.7.4 (#727) --- README.rst | 2 +- performance_tests/README.rst | 2 +- performance_tests/requirements_mpl.txt | 2 +- requirements_mpl.txt | 2 +- setup.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 5ff192733..b968ae13e 100644 --- a/README.rst +++ b/README.rst @@ -42,7 +42,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: == 1.7.2 +* aws-cryptographic-material-providers: == 1.7.4 * Requires Python 3.11+. Installation diff --git a/performance_tests/README.rst b/performance_tests/README.rst index 8ec315343..ee3dd797b 100644 --- a/performance_tests/README.rst +++ b/performance_tests/README.rst @@ -49,7 +49,7 @@ Required Prerequisites Recommended Prerequisites ========================= -* aws-cryptographic-material-providers: == 1.7.2 +* aws-cryptographic-material-providers: == 1.7.4 * Requires Python 3.11+. ***** diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt index 77c6460a5..1615fff0d 100644 --- a/performance_tests/requirements_mpl.txt +++ b/performance_tests/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers==1.7.2 \ No newline at end of file +aws-cryptographic-material-providers==1.7.4 \ No newline at end of file diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 58c7d2012..f1a309033 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers==1.7.2 +aws-cryptographic-material-providers==1.7.4 diff --git a/setup.py b/setup.py index dfbf91664..ab5ac71a3 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def get_requirements(): # TODO-MPL: Point at PyPI once MPL is released. # This blocks releasing ESDK-Python MPL integration. extras_require={ - "MPL": ["aws-cryptographic-material-providers==1.7.2"], + "MPL": ["aws-cryptographic-material-providers==1.7.4"], }, classifiers=[ "Development Status :: 5 - Production/Stable", From f8876fb3d04954664a194be51662cb8435ebc6dd Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 13 Nov 2024 10:49:35 -0800 Subject: [PATCH 49/51] m --- test_vector_handlers/tox.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test_vector_handlers/tox.ini b/test_vector_handlers/tox.ini index cdb1137fb..7fe77ff50 100644 --- a/test_vector_handlers/tox.ini +++ b/test_vector_handlers/tox.ini @@ -51,6 +51,9 @@ deps = -rtest/requirements.txt # Install the MPL requirements if the `-mpl` suffix is present mpl: -rrequirements_mpl.txt + # This is the filepath used in ESDK-Python's integration tests. + # You may need to change this to run this project locally. + mpl: scripts/aws-cryptographic-material-providers-library/TestVectorsAwsCryptographicMaterialProviders/runtimes/python .. commands = awses_local: {[testenv:base-command]commands} From 4d99d0c5f82337f62520b149b507dcc19827082f Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 15 Nov 2024 14:39:48 -0800 Subject: [PATCH 50/51] m --- .github/workflows/ci_codebuild-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_codebuild-tests.yml b/.github/workflows/ci_codebuild-tests.yml index 79a5841e0..3910c70d6 100644 --- a/.github/workflows/ci_codebuild-tests.yml +++ b/.github/workflows/ci_codebuild-tests.yml @@ -41,7 +41,7 @@ jobs: role-duration-seconds: 4200 - name: Run python-${{ matrix.python.python_version }} ${{ matrix.codebuild_file_name }} uses: aws-actions/aws-codebuild-run-build@v1 - timeout-minutes: 70 + timeout-minutes: 65 with: project-name: python-esdk buildspec-override: codebuild/py${{ matrix.python.python_version }}/${{ matrix.codebuild_file_name }} From d8b65173ce050b0dcd3b23080c9d4b6954bec039 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 21 Nov 2024 09:12:56 -0800 Subject: [PATCH 51/51] Update ci_codebuild-tests.yml --- .github/workflows/ci_codebuild-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_codebuild-tests.yml b/.github/workflows/ci_codebuild-tests.yml index 3910c70d6..79a5841e0 100644 --- a/.github/workflows/ci_codebuild-tests.yml +++ b/.github/workflows/ci_codebuild-tests.yml @@ -41,7 +41,7 @@ jobs: role-duration-seconds: 4200 - name: Run python-${{ matrix.python.python_version }} ${{ matrix.codebuild_file_name }} uses: aws-actions/aws-codebuild-run-build@v1 - timeout-minutes: 65 + timeout-minutes: 70 with: project-name: python-esdk buildspec-override: codebuild/py${{ matrix.python.python_version }}/${{ matrix.codebuild_file_name }}