Skip to content

Commit

Permalink
feat: AWS KMS multi-Region Key support (#216)
Browse files Browse the repository at this point in the history
CLI now supports Multi-Region Keys (MRKs).
Usage of MRKs is identical to the usage of non-MRK KMS Keys.
Though a KMS Key does not have to be a MRK Key for it to be used.

See https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html
for more details about AWS KMS multi-Region Keys.
See https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks
for more details about how the AWS Encryption SDK interoperates
with AWS KMS multi-Region keys.
  • Loading branch information
seebees authored Jun 16, 2021
1 parent c6b0253 commit b04688c
Show file tree
Hide file tree
Showing 15 changed files with 67 additions and 19 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@
Changelog
*********

3.0.0 -- 2021-06-16
===================

Features
--------
* AWS KMS multi-Region Key support

CLI now supports Multi-Region Keys (MRKs).
Usage of MRKs is identical to the usage of non-MRK KMS Keys.
Though a KMS Key does not have to be a MRK key for it to be used.

See https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html
for more details about AWS KMS multi-Region Keys.

See https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html#config-mrks
for more details about how the AWS Encryption SDK interoperates
with AWS KMS multi-Region keys.

2.2.0 -- 2021-05-27
===================

Expand Down
1 change: 1 addition & 0 deletions api_compatibility_tests/compatibility-requirements/3.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aws-encryption-sdk-cli==3.0.0
10 changes: 8 additions & 2 deletions api_compatibility_tests/tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
envlist =
py38-awses_cli_{1.7.0,1.8.0,1.9.0,2.0.0,2.1.0,2.2.0}
py38-awses_cli_{1.7.0,1.8.0,1.9.0,2.0.0,2.1.0,2.2.0,3.0.0}

[testenv:base-command]
commands = pytest --basetemp={envtmpdir} -l test/ {posargs}
Expand All @@ -9,13 +9,18 @@ commands = pytest --basetemp={envtmpdir} -l test/ {posargs}
passenv =
# Identifies AWS KMS key id to use in integration tests
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID \
# Identifies AWS MRK KMS key id to use in integration tests
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1 \
# 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 \
# Pass through custom pip config file settings
# The region for the MRK aware components
AWS_REGION \
AWS_DEFAULT_REGION \
# Pass through custom pip config file settings
PIP_CONFIG_FILE
sitepackages = False
deps =
Expand All @@ -26,6 +31,7 @@ deps =
awses_cli_2.0.0: -rcompatibility-requirements/2.0.0
awses_cli_2.1.0: -rcompatibility-requirements/2.1.0
awses_cli_2.2.0: -rcompatibility-requirements/2.2.0
awses_cli_3.0.0: -rcompatibility-requirements/3.0.0
awses_cli_local: -e {env:AWSES_CLI_LOCAL_PATH}
commands =
{[testenv:base-command]commands}
2 changes: 2 additions & 0 deletions codebuild/python_27.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ env:
TOXENV: "py27-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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 2 additions & 0 deletions codebuild/python_35.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ env:
TOXENV: "py35-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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 2 additions & 0 deletions codebuild/python_36.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ env:
TOXENV: "py36-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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 2 additions & 0 deletions codebuild/python_37.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ env:
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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 2 additions & 0 deletions codebuild/python_38.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ env:
TOXENV: "py38-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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 2 additions & 0 deletions codebuild/release/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ 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_MRK_KEY_ID_1: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
phases:
install:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
base64io>=1.0.1
aws-encryption-sdk~=2.2
aws-encryption-sdk~=2.3
setuptools
attrs>=17.1.0
2 changes: 1 addition & 1 deletion src/aws_encryption_sdk_cli/internal/identifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"DEFAULT_MASTER_KEY_PROVIDER",
"OperationResult",
)
__version__ = "2.2.0" # type: str
__version__ = "3.0.0" # type: str

#: Suffix added to output files if specific output filename is not specified.
OUTPUT_SUFFIX = {
Expand Down
22 changes: 14 additions & 8 deletions src/aws_encryption_sdk_cli/key_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
import copy

import botocore.session
from aws_encryption_sdk import DiscoveryAwsKmsMasterKeyProvider, StrictAwsKmsMasterKeyProvider
from aws_encryption_sdk.key_providers.kms import DiscoveryFilter
from aws_encryption_sdk.key_providers.kms import (
DiscoveryFilter,
MRKAwareDiscoveryAwsKmsMasterKeyProvider,
MRKAwareStrictAwsKmsMasterKeyProvider,
)

from aws_encryption_sdk_cli.exceptions import BadUserArgumentError
from aws_encryption_sdk_cli.internal.identifiers import USER_AGENT_SUFFIX
Expand All @@ -29,13 +32,16 @@
__all__ = ("aws_kms_master_key_provider",)


def aws_kms_master_key_provider(discovery=True, **kwargs):
# type: (bool, **List[Union[Text, str]]) -> Union[DiscoveryAwsKmsMasterKeyProvider, StrictAwsKmsMasterKeyProvider]
def aws_kms_master_key_provider(
discovery=True, # type: bool
**kwargs # type: List[Union[Text, str]]
):
# type: (...) -> Union[MRKAwareDiscoveryAwsKmsMasterKeyProvider, MRKAwareStrictAwsKmsMasterKeyProvider]
"""Apply post-processing to transform ``KMSMasterKeyProvider``-specific values from CLI
arguments to valid ``KMSMasterKeyProvider`` parameters, then call ``KMSMasterKeyprovider``
arguments to valid ``KMSMasterKeyProvider`` parameters, then call ``KMSMasterKeyProvider``
with those parameters.
:param bool discovery: Return a DiscoveryAwsKmsMasterKeyProvider
:param bool discovery: Return a MRKAwareDiscoveryAwsKmsMasterKeyProvider
:param dict kwargs: Named parameters collected from CLI arguments as prepared
in aws_encryption_sdk_cli.internal.master_key_parsing._parse_master_key_providers_from_args
:rtype: aws_encryption_sdk.key_providers.kms.BaseKMSMasterKeyProvider
Expand Down Expand Up @@ -75,5 +81,5 @@ def aws_kms_master_key_provider(discovery=True, **kwargs):
discovery_filter = DiscoveryFilter(account_ids=accounts, partition=partition)
kwargs["discovery_filter"] = discovery_filter # type: ignore

return DiscoveryAwsKmsMasterKeyProvider(**kwargs)
return StrictAwsKmsMasterKeyProvider(**kwargs)
return MRKAwareDiscoveryAwsKmsMasterKeyProvider(**kwargs)
return MRKAwareStrictAwsKmsMasterKeyProvider(**kwargs)
2 changes: 1 addition & 1 deletion test/unit/test_aws_encryption_sdk_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ def test_cli_unknown_error_capture_stacktrace(patch_process_cli_request, tmpdir,
+ str(tmpdir.join("ciphertext"))
+ " "
+ requested_log_level
+ " -w discovery=true"
+ " -w discovery=true region=us-west-2"
)
)

Expand Down
8 changes: 4 additions & 4 deletions test/unit/test_key_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ def patch_botocore_session(mocker):

@pytest.yield_fixture
def patch_discovery_master_key_provider(mocker):
mocker.patch.object(key_providers, "DiscoveryAwsKmsMasterKeyProvider")
yield key_providers.DiscoveryAwsKmsMasterKeyProvider
mocker.patch.object(key_providers, "MRKAwareDiscoveryAwsKmsMasterKeyProvider")
yield key_providers.MRKAwareDiscoveryAwsKmsMasterKeyProvider


@pytest.yield_fixture
def patch_strict_master_key_provider(mocker):
mocker.patch.object(key_providers, "StrictAwsKmsMasterKeyProvider")
yield key_providers.StrictAwsKmsMasterKeyProvider
mocker.patch.object(key_providers, "MRKAwareStrictAwsKmsMasterKeyProvider")
yield key_providers.MRKAwareStrictAwsKmsMasterKeyProvider


@pytest.mark.parametrize(
Expand Down
9 changes: 7 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,17 @@ envlist =
passenv =
# Identifies AWS KMS key id to use in integration tests
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID \
# Identifies AWS MRK KMS key id to use in integration tests
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1 \
# 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 \
# The region for the MRK aware components
AWS_REGION \
AWS_DEFAULT_REGION \
# Pass through custom pip config file settings
PIP_CONFIG_FILE

Expand Down Expand Up @@ -78,8 +83,8 @@ basepython = python3
deps =
# mypy outputs coverage data in a coverage 4.x format
coverage~=4.0
mypy
mypy_extensions
mypy==0.812
mypy_extensions==0.4.3
typing>=3.6.2

[testenv:mypy-py3]
Expand Down

0 comments on commit b04688c

Please sign in to comment.