From 9d99241b04a56aa7eb5e0dcb9c3f7e52e09f2f74 Mon Sep 17 00:00:00 2001 From: Matt Bullock Date: Wed, 2 Oct 2019 16:26:20 -0700 Subject: [PATCH] Fix botocore regional client use to avoid issues in #124 (#125) * add extra itertools-like permuter helpers * add permuted valid arguments test for AwsKmsCryptographicMaterialsProvider * fix AwsKmsCryptographicMaterialsProvider.__attrs_post_init__ value override fixes https://github.com/aws/aws-dynamodb-encryption-python/issues/124 * update changelog with #124 fix * specify region_name in test value --- CHANGELOG.rst | 8 +++++ .../material_providers/aws_kms.py | 3 -- test/unit/material_providers/test_aws_kms.py | 34 +++++++++++++++++++ test/unit/unit_test_utils.py | 15 ++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f3c6ef17..79b7fac6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog ********* +1.1.2 -- 2019-09-?? +=================== + +Bugfixes +-------- +* Fix :class:`AwsKmsCryptographicMaterialsProvider` regional clients override bug + `#124 `_ + 1.1.1 -- 2019-08-29 =================== diff --git a/src/dynamodb_encryption_sdk/material_providers/aws_kms.py b/src/dynamodb_encryption_sdk/material_providers/aws_kms.py index 2a8b9fb7..7fa47854 100644 --- a/src/dynamodb_encryption_sdk/material_providers/aws_kms.py +++ b/src/dynamodb_encryption_sdk/material_providers/aws_kms.py @@ -214,9 +214,6 @@ def __attrs_post_init__(self): default_algorithm=_DEFAULT_SIGNING_ALGORITHM, default_key_length=_DEFAULT_SIGNING_KEY_LENGTH, ) - self._regional_clients = ( - {} - ) # type: Dict[Text, botocore.client.BaseClient] # noqa pylint: disable=attribute-defined-outside-init def _add_regional_client(self, region_name): # type: (Text) -> None diff --git a/test/unit/material_providers/test_aws_kms.py b/test/unit/material_providers/test_aws_kms.py index a1166dba..efedfd90 100644 --- a/test/unit/material_providers/test_aws_kms.py +++ b/test/unit/material_providers/test_aws_kms.py @@ -32,6 +32,8 @@ ) from dynamodb_encryption_sdk.structures import EncryptionContext +from ..unit_test_utils import all_possible_combinations_kwargs + pytestmark = [pytest.mark.unit, pytest.mark.local] _VALID_KEY_INFO_KWARGS = dict(description="some string", algorithm="algorithm name", length=1234) @@ -218,6 +220,38 @@ def test_loaded_key_infos(): assert cmp._regional_clients == {} +@pytest.mark.parametrize( + "kwargs", + [ + pytest.param(val, id=str(val)) + for val in all_possible_combinations_kwargs( + dict(), + dict(botocore_session=botocore.session.Session()), + dict(grant_tokens=("sdvoaweih", "auwshefiouawh")), + dict(material_description={"asoiufeoia": "soajfijewi"}), + dict( + regional_clients={ + "my-region-1": boto3.session.Session().client( + "kms", region_name="not-a-real-region", endpoint_url="https://not-a-real-url" + ) + } + ), + ) + ], +) +def test_kms_cmp_values_set(kwargs): + cmp = AwsKmsCryptographicMaterialsProvider(key_id="example_key_id", **kwargs) + + assert cmp._key_id == "example_key_id" + + if "botocore_session" in kwargs: + assert cmp._botocore_session == kwargs["botocore_session"] + + assert cmp._grant_tokens == kwargs.get("grant_tokens", ()) + assert cmp._material_description == kwargs.get("material_description", {}) + assert cmp._regional_clients == kwargs.get("regional_clients", {}) + + def test_add_regional_client_known_region(default_kms_cmp, patch_boto3_session): default_kms_cmp._regional_clients[sentinel.region] = sentinel.client diff --git a/test/unit/unit_test_utils.py b/test/unit/unit_test_utils.py index 44c8b653..26f19fcb 100644 --- a/test/unit/unit_test_utils.py +++ b/test/unit/unit_test_utils.py @@ -11,6 +11,8 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Helper utilities for unit tests.""" +import itertools + import pytest from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey @@ -25,3 +27,16 @@ def wrapped_cmp(): signing_key=signing_key, wrapping_key=wrapping_key, unwrapping_key=wrapping_key ) return cmp + + +def all_possible_combinations(*base_values): + combinations = [itertools.combinations(base_values, i) for i in range(1, len(base_values) + 1)] + return itertools.chain(*combinations) + + +def all_possible_combinations_kwargs(*base_values): + for combo in all_possible_combinations(*base_values): + kwargs = {} + for values in combo: + kwargs.update(values) + yield kwargs