def test_add_master_keys_invalid_arn(self, non_arn): """ Check that the Strict MRK-aware provider uses the default region when creating a new key with an invalid arn. """ with patch.object(self.mock_botocore_session, "get_config_variable", return_value="us-west-2") as mock_get_config: provider = MRKAwareStrictAwsKmsMasterKeyProvider( botocore_session=self.mock_botocore_session, key_ids=[non_arn]) master_key = provider._new_master_key(non_arn) mock_get_config.assert_called_with("region") assert master_key.__class__ == MRKAwareKMSMasterKey assert master_key._key_id == non_arn self.mock_boto3_session.assert_called_with(botocore_session=ANY) self.mock_boto3_session_instance.client.assert_called_with( "kms", region_name="us-west-2", config=provider._user_agent_adding_config, )
def test_add_master_keys_class(self): """Check that the MRK-aware provider creates MRKAwareKMSMasterKeys""" grant_tokens = (sentinel.grant_token2, sentinel.grant_token2) key_id = "arn:aws:kms:eu-west-2:222222222222:key/mrk-aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb" provider = MRKAwareStrictAwsKmsMasterKeyProvider( key_ids=[key_id], grant_tokens=grant_tokens) master_key = provider._new_master_key(key_id) # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 # //= type=test # //# In strict mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware- # //# master-key.md) MUST be returned configured with assert master_key.__class__ == MRKAwareKMSMasterKey assert "eu-west-2" in master_key._key_id self.mock_boto3_session.assert_called_with(botocore_session=ANY) self.mock_boto3_session_instance.client.assert_called_with( "kms", region_name="eu-west-2", config=provider._user_agent_adding_config, ) assert master_key.config.grant_tokens is grant_tokens
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`` with those parameters. :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 """ kwargs = copy.deepcopy(kwargs) try: profile_names = kwargs.pop("profile") if len(profile_names) != 1: raise BadUserArgumentError( "Only one profile may be specified per master key provider configuration. {} provided." .format(len(profile_names))) profile_name = profile_names[0] # type: Optional[Text] except KeyError: profile_name = None botocore_session = botocore.session.Session(profile=profile_name) botocore_session.user_agent_extra = USER_AGENT_SUFFIX kwargs["botocore_session"] = botocore_session try: region_name = kwargs.pop("region") if len(region_name) != 1: raise BadUserArgumentError( "Only one region may be specified per master key provider configuration. {} provided." .format(len(region_name))) kwargs["region_names"] = region_name except KeyError: pass if discovery: accounts = kwargs.pop("discovery-account", None) partition = kwargs.pop("discovery-partition", None) if accounts and partition: discovery_filter = DiscoveryFilter(account_ids=accounts, partition=partition) kwargs["discovery_filter"] = discovery_filter # type: ignore return MRKAwareDiscoveryAwsKmsMasterKeyProvider(**kwargs) return MRKAwareStrictAwsKmsMasterKeyProvider(**kwargs)
def test_init_requires_unique_mrks(self): # //= compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 # //= type=test # //# If any duplicate multi-region resource ids exist, this function MUST # //# yield an error that includes all identifiers with duplicate resource # //# ids not only the first duplicate found. key_ids = ( "arn:aws:kms:eu-west-2:222222222222:key/mrk-aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "arn:aws:kms:us-east-1:222222222222:key/mrk-aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "mrk-aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "arn:aws:kms:eu-west-2:222222222222:key/aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", ) expected_error_string = "Configured key ids must be unique. Found related MRKs: .*, .*, .*" with patch.object(self.mock_botocore_session, "get_config_variable", return_value="us-west-2"): with pytest.raises(ConfigMismatchError) as excinfo: MRKAwareStrictAwsKmsMasterKeyProvider( botocore_session=self.mock_botocore_session, key_ids=key_ids) excinfo.match(expected_error_string)
def test_init_with_duplicate_non_mrk_key_ids(self): # //= compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 # //= type=test # //# If the list does not contain any multi-Region keys (aws-kms-key- # //# arn.md#identifying-an-aws-kms-multi-region-key) this function MUST # //# exit successfully. key_ids = ( "arn:aws:kms:eu-west-2:222222222222:key/aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "arn:aws:kms:eu-west-2:222222222222:key/aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "alias/myAlias", "alias/myAlias", ) with patch.object(self.mock_botocore_session, "get_config_variable", return_value="us-west-2"): provider = MRKAwareStrictAwsKmsMasterKeyProvider( botocore_session=self.mock_botocore_session, key_ids=key_ids) assert len(provider.config.key_ids) == 4 assert key_ids[0] in provider.config.key_ids assert key_ids[1] in provider.config.key_ids assert key_ids[2] in provider.config.key_ids assert key_ids[3] in provider.config.key_ids
def test_init_with_key_ids(self): # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6 # //= type=test # //# All AWS KMS # //# key identifiers are be passed to Assert AWS KMS MRK are unique (aws- # //# kms-mrk-are-unique.md#Implementation) and the function MUST return # //# success. # //= compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 # //= type=test # //# The caller MUST provide: # //= compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5 # //= type=test # //# If there are zero duplicate resource ids between the multi-region # //# keys, this function MUST exit successfully key_ids = ( "arn:aws:kms:eu-west-2:222222222222:key/mrk-aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "arn:aws:kms:us-east-1:222222222222:key/mrk-bbbbbbbb-1111-2222-3333-bbbbbbbbbbbb", ) provider = MRKAwareStrictAwsKmsMasterKeyProvider(key_ids=key_ids) assert len(provider.config.key_ids) == 2 assert key_ids[0] in provider.config.key_ids assert key_ids[1] in provider.config.key_ids
def encrypt_decrypt(mrk_arn, mrk_arn_second_region, source_plaintext): """Illustrates usage of KMS Multi-Region Keys. :param str mrk_arn: Amazon Resource Name (ARN) of the first KMS MRK :param str mrk_arn_second_region: Amazon Resource Name (ARN) of a related KMS MRK in a different region :param bytes source_plaintext: Data to encrypt """ # Encrypt in the first region # 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) # For this example, set mrk_arn to be a Multi-Region key. # Multi-Region keys have a distinctive key ID that begins with 'mrk'. # For example: "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab". # Create a Strict Multi-Region Key Aware Master Key Provider which targets the Multi-Region key ARN. kwargs = dict(key_ids=[mrk_arn]) strict_key_provider = MRKAwareStrictAwsKmsMasterKeyProvider(**kwargs) # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header ciphertext, _ = client.encrypt(source=source_plaintext, key_provider=strict_key_provider) # Decrypt in a second region # For this example, set mrk_arn_second_region to be Multi-Region key related to key_arn. # Related multi-Region keys have the same key ID. Their key ARNs differs only in the Region field. # For example: "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab" # Create a Strict Multi-Region Key Aware Master Key Provider which targets the Multi-Region key in the second region kwargs = dict(key_ids=[mrk_arn_second_region]) strict_key_provider_region_2 = MRKAwareStrictAwsKmsMasterKeyProvider( **kwargs) # Decrypt your ciphertext plaintext, _ = client.decrypt(source=ciphertext, key_provider=strict_key_provider_region_2) # Verify that the original message and the decrypted message are the same assert source_plaintext == plaintext # Decrypt in discovery mode in a second region # First determine what region you want to perform discovery in, as well as what # accounts and partition you want to allow if using a Discovery Filter. # In this example, we just want to use whatever region, account, and partition # our second key is in, in order to ensure we can discover it. # Note that the ARN itself is never used in the configuration. arn = arn_from_str(mrk_arn_second_region) discovery_region = arn.region filter_accounts = [arn.account_id] filter_partition = arn.partition # Configure a Discovery Region and optional Discovery Filter decrypt_kwargs = dict( discovery_filter=DiscoveryFilter(account_ids=filter_accounts, partition=filter_partition), discovery_region=discovery_region, ) # Create an MRK-aware master key provider in discovery mode that targets the second region. # This will cause the provider to try to decrypt using this region whenever it encounters an MRK. discovery_key_provider = MRKAwareDiscoveryAwsKmsMasterKeyProvider( **decrypt_kwargs) # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header. plaintext, _ = client.decrypt(source=ciphertext, key_provider=discovery_key_provider) # Verify that the original message and the decrypted message are the same assert source_plaintext == plaintext