def _new_master_key(self, key_id):
        """Returns a KMSMasterKey for the specified key_id.

        :param bytes key_id: KMS CMK ID
        :returns: KMS Master Key based on key_id
        :rtype: aws_encryption_sdk.key_providers.kms.KMSMasterKey
        :raises InvalidKeyIdError: if key_id is not a valid KMS CMK ID to which this key provider has access
        :raises MasterKeyProviderError: if this MasterKeyProvider is in discovery mode and key_id is not allowed
        """
        _key_id = to_str(key_id)  # KMS client requires str, not bytes

        if self.config.discovery_filter:
            arn = arn_from_str(_key_id)

            if (arn.partition != self.config.discovery_filter.partition
                    or arn.account_id
                    not in self.config.discovery_filter.account_ids):
                # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
                # //# In discovery mode if a discovery filter is configured the requested AWS
                # //# KMS key ARN's "partition" MUST match the discovery filter's
                # //# "partition" and the AWS KMS key ARN's "account" MUST exist in the
                # //# discovery filter's account id set.
                raise MasterKeyProviderError(
                    "Key {} not allowed by this Master Key Provider".format(
                        key_id))
        return self._new_master_key_impl(key_id)
示例#2
0
 def __init__(self, **kwargs):  # pylint: disable=unused-argument
     """Performs transformations needed for KMS."""
     self._key_id = to_str(
         self.key_id)  # KMS client requires str, not bytes
     self.config.client.meta.config.user_agent_extra = extend_user_agent_suffix(
         user_agent=self.config.client.meta.config.user_agent_extra,
         suffix=USER_AGENT_SUFFIX)
def _deserialize_encrypted_data_keys(stream):
    # type: (IO) -> Set[EncryptedDataKey]
    """Deserialize some encrypted data keys from a stream.

    :param stream: Stream from which to read encrypted data keys
    :return: Loaded encrypted data keys
    :rtype: set of :class:`EncryptedDataKey`
    """
    (encrypted_data_key_count,) = unpack_values(">H", stream)
    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length,) = unpack_values(">H", stream)
        (key_provider_identifier,) = unpack_values(">{}s".format(key_provider_length), stream)
        (key_provider_information_length,) = unpack_values(">H", stream)
        (key_provider_information,) = unpack_values(">{}s".format(key_provider_information_length), stream)
        (encrypted_data_key_length,) = unpack_values(">H", stream)
        encrypted_data_key = stream.read(encrypted_data_key_length)
        encrypted_data_keys.add(
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=to_str(key_provider_identifier), key_info=key_provider_information
                ),
                encrypted_data_key=encrypted_data_key,
            )
        )
    return encrypted_data_keys
def deserialize_encrypted_data_keys(stream, max_encrypted_data_keys=None):
    # type: (IO, Union[int, None]) -> Set[EncryptedDataKey]
    """Deserialize some encrypted data keys from a stream.

    :param stream: Stream from which to read encrypted data keys
    :param max_encrypted_data_keys: Maximum number of encrypted data keys to deserialize
    :return: Loaded encrypted data keys
    :rtype: set of :class:`EncryptedDataKey`
    """
    (encrypted_data_key_count, ) = unpack_values(">H", stream)
    if max_encrypted_data_keys and encrypted_data_key_count > max_encrypted_data_keys:
        raise MaxEncryptedDataKeysExceeded(encrypted_data_key_count,
                                           max_encrypted_data_keys)
    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length, ) = unpack_values(">H", stream)
        (key_provider_identifier, ) = unpack_values(
            ">{}s".format(key_provider_length), stream)
        (key_provider_information_length, ) = unpack_values(">H", stream)
        (key_provider_information, ) = unpack_values(
            ">{}s".format(key_provider_information_length), stream)
        (encrypted_data_key_length, ) = unpack_values(">H", stream)
        encrypted_data_key = stream.read(encrypted_data_key_length)
        encrypted_data_keys.add(
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=to_str(key_provider_identifier),
                    key_info=key_provider_information),
                encrypted_data_key=encrypted_data_key,
            ))
    return encrypted_data_keys
示例#5
0
 def __init__(self, **kwargs):
     self._key_id = to_str(self.key_id)  # KMS client requires str, not bytes
     self.config.client.meta.config.user_agent = (
         'Botocore-KMSMasterKey/{version}/{botocore_version}'
     ).format(
         version=__version__,
         botocore_version=botocore.__version__
     )
示例#6
0
 def client_default(self):
     """Create a client if one was not provided."""
     try:
         region_name = _region_from_key_id(to_str(self.key_id))
         kwargs = dict(region_name=region_name)
     except UnknownRegionError:
         kwargs = {}
     botocore_config = botocore.config.Config(user_agent_extra=USER_AGENT_SUFFIX)
     return boto3.session.Session(**kwargs).client('kms', config=botocore_config)
    def test_new_master_key_with_discovery_filter_success(self, mock_client):
        mock_client.return_value = self.mock_boto3_client_instance
        key_info = b"arn:aws:kms:us-east-1:222222222222:key/aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb"
        test = UnitTestBaseKMSMasterKeyProvider()
        test.config.discovery_filter = DiscoveryFilter(
            partition="aws", account_ids=["222222222222"])

        key = test._new_master_key(key_info)
        assert key.key_id == key_info
        mock_client.assert_called_with(to_str(key_info))
    def _new_master_key_impl(self, key_id):
        """The actual creation of new master keys. Separated out from _new_master_key so that we can share the
        validation logic while also allowing subclasses to implement different logic for instantiation of the key
        itself.
        """
        _key_id = to_str(key_id)  # KMS client requires str, not bytes

        return self.master_key_class(config=self.master_key_config_class(
            key_id=key_id,
            client=self._client(_key_id),
            grant_tokens=self.config.grant_tokens))
    def _new_master_key(self, key_id):
        """Returns a KMSMasterKey for the specified key_id.

        :param bytes key_id: KMS CMK ID
        :returns: KMS Master Key based on key_id
        :rtype: aws_encryption_sdk.key_providers.kms.KMSMasterKey
        :raises InvalidKeyIdError: if key_id is not a valid KMS CMK ID to which this key provider has access
        """
        _key_id = to_str(key_id)  # KMS client requires str, not bytes
        return KMSMasterKey(config=KMSMasterKeyConfig(
            key_id=key_id, client=self._client(_key_id)))
示例#10
0
    def owns_data_key(self, data_key):
        """Determines if data_key object is owned by this MasterKey. This method overrides the method from the base
        class, because for MRKs we need to check for MRK equality on the key ids rather than exact string equality.

        :param data_key: Data key to evaluate
        :type data_key: :class:`aws_encryption_sdk.structures.DataKey`,
            :class:`aws_encryption_sdk.structures.RawDataKey`,
            or :class:`aws_encryption_sdk.structures.EncryptedDataKey`
        :returns: Boolean statement of ownership
        :rtype: bool
        """
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9
        # //# To match the encrypted data key's
        # //# provider ID MUST exactly match the value "aws-kms" and the the
        # //# function AWS KMS MRK Match for Decrypt (aws-kms-mrk-match-for-
        # //# decrypt.md#implementation) called with the configured AWS KMS key
        # //# identifier and the encrypted data key's provider info MUST return
        # //# "true".
        if data_key.key_provider.provider_id == self.key_provider.provider_id and _check_mrk_arns_equal(
                to_str(data_key.key_provider.key_info),
                to_str(self.key_provider.key_info)):
            return True
        return False
示例#11
0
    def _decrypt_data_key(self,
                          encrypted_data_key,
                          algorithm,
                          encryption_context=None):
        """Decrypts an encrypted data key and returns the plaintext.

        :param data_key: Encrypted data key
        :type data_key: aws_encryption_sdk.structures.EncryptedDataKey
        :type algorithm: `aws_encryption_sdk.identifiers.Algorithm` (not used for KMS)
        :param dict encryption_context: Encryption context to use in decryption
        :returns: Decrypted data key
        :rtype: aws_encryption_sdk.structures.DataKey
        :raises DecryptKeyError: if Master Key is unable to decrypt data key
        """
        edk_key_id = to_str(encrypted_data_key.key_provider.key_info)
        if edk_key_id != self._key_id:
            raise DecryptKeyError(
                "Cannot decrypt EDK wrapped by key_id={}, because it does not match this "
                "provider's key_id={}".format(edk_key_id, self._key_id))

        kms_params = {
            "CiphertextBlob": encrypted_data_key.encrypted_data_key,
            "KeyId": edk_key_id
        }
        if encryption_context:
            kms_params["EncryptionContext"] = encryption_context
        if self.config.grant_tokens:
            kms_params["GrantTokens"] = self.config.grant_tokens
        # Catch any boto3 errors and normalize to expected DecryptKeyError
        try:
            response = self.config.client.decrypt(**kms_params)

            returned_key_id = response["KeyId"]
            if returned_key_id != edk_key_id:
                error_message = "AWS KMS returned unexpected key_id {returned} (expected {key_id})".format(
                    returned=returned_key_id, key_id=edk_key_id)
                _LOGGER.exception(error_message)
                raise DecryptKeyError(error_message)
            plaintext = response["Plaintext"]
        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to decrypt data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise DecryptKeyError(error_message)
        return DataKey(
            key_provider=self.key_provider,
            data_key=plaintext,
            encrypted_data_key=encrypted_data_key.encrypted_data_key)
    def test_new_master_key_with_discovery_filter_success(self, mock_client):
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
        # //= type=test
        # //# In discovery mode if a discovery filter is configured the requested AWS
        # //# KMS key ARN's "partition" MUST match the discovery filter's
        # //# "partition" and the AWS KMS key ARN's "account" MUST exist in the
        # //# discovery filter's account id set.
        mock_client.return_value = self.mock_boto3_client_instance
        key_info = b"arn:aws:kms:us-east-1:222222222222:key/aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb"
        test = UnitTestBaseKMSMasterKeyProvider()
        test.config.discovery_filter = DiscoveryFilter(
            partition="aws", account_ids=["222222222222"])

        key = test._new_master_key(key_info)
        assert key.key_id == key_info
        mock_client.assert_called_with(to_str(key_info))
示例#13
0
    def _generate_data_key(self, algorithm, encryption_context=None):
        """Generates data key and returns plaintext and ciphertext of key.

        :param algorithm: Algorithm on which to base data key
        :type algorithm: aws_encryption_sdk.identifiers.Algorithm
        :param dict encryption_context: Encryption context to pass to KMS
        :returns: Generated data key
        :rtype: aws_encryption_sdk.structures.DataKey
        """
        kms_params = self._build_generate_data_key_request(
            algorithm, encryption_context)
        # Catch any boto3 errors and normalize to expected EncryptKeyError
        try:
            response = self.config.client.generate_data_key(**kms_params)
            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
            # //# The response's "Plaintext" MUST be the plaintext in the output.
            plaintext = response["Plaintext"]
            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
            # //# The response's cipher text blob MUST be used as the returned as the
            # //# ciphertext for the encrypted data key in the output.
            ciphertext = response["CiphertextBlob"]
            key_id = response["KeyId"]
        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to generate data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise GenerateKeyError(error_message)

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //# The response's "KeyId" MUST be valid.
        # arn_from_str will error if given an invalid key ARN
        try:
            key_id_str = to_str(key_id)
            arn_from_str(key_id_str)
        except MalformedArnError:
            error_message = "Retrieved an unexpected KeyID in response from KMS: {key_id}".format(
                key_id=key_id)
            _LOGGER.exception(error_message)
            raise GenerateKeyError(error_message)

        return DataKey(
            key_provider=MasterKeyInfo(provider_id=self.provider_id,
                                       key_info=key_id),
            data_key=plaintext,
            encrypted_data_key=ciphertext,
        )
    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()
示例#15
0
    def _encrypt_data_key(self, data_key, algorithm, encryption_context=None):
        """Encrypts a data key and returns the ciphertext.

        :param data_key: Unencrypted data key
        :type data_key: :class:`aws_encryption_sdk.structures.RawDataKey`
            or :class:`aws_encryption_sdk.structures.DataKey`
        :param algorithm: Placeholder to maintain API compatibility with parent
        :param dict encryption_context: Encryption context to pass to KMS
        :returns: Data key containing encrypted data key
        :rtype: aws_encryption_sdk.structures.EncryptedDataKey
        :raises EncryptKeyError: if Master Key is unable to encrypt data key
        """
        kms_params = self._build_encrypt_request(data_key, encryption_context)
        # Catch any boto3 errors and normalize to expected EncryptKeyError
        try:
            response = self.config.client.encrypt(**kms_params)
            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
            # //# The response's cipher text blob MUST be used as the "ciphertext" for the
            # //# encrypted data key.
            ciphertext = response["CiphertextBlob"]
            key_id = response["KeyId"]
        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to encrypt data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise EncryptKeyError(error_message)

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
        # //# The AWS KMS Encrypt response MUST contain a valid "KeyId".
        # arn_from_str will error if given an invalid key ARN
        try:
            key_id_str = to_str(key_id)
            arn_from_str(key_id_str)
        except MalformedArnError:
            error_message = "Retrieved an unexpected KeyID in response from KMS: {key_id}".format(
                key_id=key_id)
            _LOGGER.exception(error_message)
            raise EncryptKeyError(error_message)

        return EncryptedDataKey(key_provider=MasterKeyInfo(
            provider_id=self.provider_id, key_info=key_id),
                                encrypted_data_key=ciphertext)
示例#16
0
    def _new_master_key_impl(self, key_id):
        """Creation of new master keys. Compared to the base class, this class has smarts to use either the configured
        discovery region or, if not present, the default SDK region, to create new keys.
        """
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
        # //# In discovery mode, the requested
        # //# AWS KMS key identifier MUST be a well formed AWS KMS ARN.
        _key_id = to_str(key_id)
        arn = arn_from_str(_key_id)

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
        # //# In discovery mode a AWS KMS MRK Aware Master Key (aws-kms-mrk-aware-
        # //# master-key.md) MUST be returned configured with
        # Note that in the MRK case we ensure the key ID passed along has the discovery region,
        # and in both cases _client(...) will ensure that a client is created that matches the key's region.

        if not arn.resource_id.startswith("mrk"):
            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
            # //# Otherwise if the requested AWS KMS key
            # //# identifier is identified as a multi-Region key (aws-kms-key-
            # //# arn.md#identifying-an-aws-kms-multi-region-key), then AWS Region MUST
            # //# be the region from the AWS KMS key ARN stored in the provider info
            # //# from the encrypted data key.
            # Note that this could return a normal KMSMasterKey and retain the same behavior,
            # however we opt to follow the spec here in order to bias towards consistency between
            # implementations.
            return MRKAwareKMSMasterKey(config=MRKAwareKMSMasterKeyConfig(
                key_id=_key_id,
                client=self._client(_key_id),
                grant_tokens=self.config.grant_tokens))
        else:
            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
            # //# Otherwise if the mode is discovery then
            # //# the AWS Region MUST be the discovery MRK region.
            arn.region = self.config.discovery_region
            new_key_id = arn.to_string()

            return MRKAwareKMSMasterKey(config=MRKAwareKMSMasterKeyConfig(
                key_id=new_key_id,
                client=self._client(new_key_id),
                grant_tokens=self.config.grant_tokens))
示例#17
0
    def _new_master_key(self, key_id):
        """Returns a KMSMasterKey for the specified key_id.

        :param bytes key_id: KMS CMK ID
        :returns: KMS Master Key based on key_id
        :rtype: aws_encryption_sdk.key_providers.kms.KMSMasterKey
        :raises InvalidKeyIdError: if key_id is not a valid KMS CMK ID to which this key provider has access
        :raises MasterKeyProviderError: if this MasterKeyProvider is in discovery mode and key_id is not allowed
        """
        _key_id = to_str(key_id)  # KMS client requires str, not bytes

        if self.config.discovery_filter:
            arn = arn_from_str(_key_id)

            if (arn.partition != self.config.discovery_filter.partition
                    or arn.account_id
                    not in self.config.discovery_filter.account_ids):
                raise MasterKeyProviderError(
                    "Key {} not allowed by this Master Key Provider".format(
                        key_id))

        return KMSMasterKey(config=KMSMasterKeyConfig(
            key_id=key_id, client=self._client(_key_id)))
示例#18
0
 def __init__(self, **kwargs):  # pylint: disable=unused-argument
     """Performs transformations needed for KMS."""
     self._key_id = to_str(
         self.key_id)  # KMS client requires str, not bytes
示例#19
0
def deserialize_header(stream):
    """Deserializes the header from a source stream

    :param stream: Source data stream
    :type stream: io.BytesIO
    :returns: Deserialized MessageHeader object
    :rtype: :class:`aws_encryption_sdk.structures.MessageHeader` and bytes
    :raises NotSupportedError: if unsupported data types are found
    :raises UnknownIdentityError: if unknown data types are found
    :raises SerializationError: if IV length does not match algorithm
    """
    _LOGGER.debug('Starting header deserialization')
    tee = io.BytesIO()
    tee_stream = TeeStream(stream, tee)
    version_id, message_type_id = unpack_values('>BB', tee_stream)
    try:
        message_type = ObjectType(message_type_id)
    except ValueError as error:
        raise NotSupportedError(
            'Unsupported type {} discovered in data stream'.format(
                message_type_id), error)
    try:
        version = SerializationVersion(version_id)
    except ValueError as error:
        raise NotSupportedError('Unsupported version {}'.format(version_id),
                                error)
    header = {'version': version, 'type': message_type}

    algorithm_id, message_id, ser_encryption_context_length = unpack_values(
        '>H16sH', tee_stream)

    try:
        alg = Algorithm.get_by_id(algorithm_id)
    except KeyError as error:
        raise UnknownIdentityError('Unknown algorithm {}'.format(algorithm_id),
                                   error)
    if not alg.allowed:
        raise NotSupportedError('Unsupported algorithm: {}'.format(alg))
    header['algorithm'] = alg
    header['message_id'] = message_id

    header['encryption_context'] = deserialize_encryption_context(
        tee_stream.read(ser_encryption_context_length))
    (encrypted_data_key_count, ) = unpack_values('>H', tee_stream)

    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length, ) = unpack_values('>H', tee_stream)
        (key_provider_identifier, ) = unpack_values(
            '>{}s'.format(key_provider_length), tee_stream)
        (key_provider_information_length, ) = unpack_values('>H', tee_stream)
        (key_provider_information, ) = unpack_values(
            '>{}s'.format(key_provider_information_length), tee_stream)
        (encrypted_data_key_length, ) = unpack_values('>H', tee_stream)
        encrypted_data_key = tee_stream.read(encrypted_data_key_length)
        encrypted_data_keys.add(
            EncryptedDataKey(key_provider=MasterKeyInfo(
                provider_id=to_str(key_provider_identifier),
                key_info=key_provider_information),
                             encrypted_data_key=encrypted_data_key))
    header['encrypted_data_keys'] = encrypted_data_keys

    (content_type_id, ) = unpack_values('>B', tee_stream)
    try:
        content_type = ContentType(content_type_id)
    except ValueError as error:
        raise UnknownIdentityError(
            'Unknown content type {}'.format(content_type_id), error)
    header['content_type'] = content_type

    (content_aad_length, ) = unpack_values('>I', tee_stream)
    if content_aad_length != 0:
        raise SerializationError(
            'Content AAD length field is currently unused, its value must be always 0'
        )
    header['content_aad_length'] = 0

    (iv_length, ) = unpack_values('>B', tee_stream)
    if iv_length != alg.iv_len:
        raise SerializationError(
            'Specified IV length ({length}) does not match algorithm IV length ({alg})'
            .format(length=iv_length, alg=alg))
    header['header_iv_length'] = iv_length

    (frame_length, ) = unpack_values('>I', tee_stream)
    if content_type == ContentType.FRAMED_DATA and frame_length > MAX_FRAME_SIZE:
        raise SerializationError(
            'Specified frame length larger than allowed maximum: {found} > {max}'
            .format(found=frame_length, max=MAX_FRAME_SIZE))
    elif content_type == ContentType.NO_FRAMING and frame_length != 0:
        raise SerializationError(
            'Non-zero frame length found for non-framed message')
    header['frame_length'] = frame_length

    return MessageHeader(**header), tee.getvalue()
示例#20
0
    def _decrypt_data_key(self,
                          encrypted_data_key,
                          algorithm,
                          encryption_context=None):
        """Decrypts an encrypted data key and returns the plaintext.

        :param data_key: Encrypted data key
        :type data_key: aws_encryption_sdk.structures.EncryptedDataKey
        :type algorithm: `aws_encryption_sdk.identifiers.Algorithm` (not used for KMS)
        :param dict encryption_context: Encryption context to use in decryption
        :returns: Decrypted data key
        :rtype: aws_encryption_sdk.structures.DataKey
        :raises DecryptKeyError: if Master Key is unable to decrypt data key
        """
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9
        # //# Additionally each provider info MUST be a valid AWS KMS ARN
        # //# (aws-kms-key-arn.md#a-valid-aws-kms-arn) with a resource type of
        # //# "key".
        edk_key_id = to_str(encrypted_data_key.key_provider.key_info)
        edk_arn = arn_from_str(edk_key_id)
        if not edk_arn.resource_type == "key":
            error_message = "AWS KMS Provider EDK contains unexpected key_id: {key_id}".format(
                key_id=edk_key_id)
            _LOGGER.exception(error_message)
            raise DecryptKeyError(error_message)

        self._validate_allowed_to_decrypt(edk_key_id)
        kms_params = self._build_decrypt_request(encrypted_data_key,
                                                 encryption_context)
        # Catch any boto3 errors and normalize to expected DecryptKeyError
        try:
            response = self.config.client.decrypt(**kms_params)

            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9
            # //# If the call succeeds then the response's "KeyId" MUST be equal to the
            # //# configured AWS KMS key identifier otherwise the function MUST collect
            # //# an error.
            # Note that Python logs but does not collect errors
            returned_key_id = response["KeyId"]
            if returned_key_id != self._key_id:
                error_message = "AWS KMS returned unexpected key_id {returned} (expected {key_id})".format(
                    returned=returned_key_id, key_id=self._key_id)
                _LOGGER.exception(error_message)
                raise DecryptKeyError(error_message)

            # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9
            # //# The response's "Plaintext"'s length MUST equal the length
            # //# required by the requested algorithm suite otherwise the function MUST
            # //# collect an error.
            # Note that Python logs but does not collect errors
            plaintext = response["Plaintext"]
            if len(plaintext) != algorithm.data_key_len:
                error_message = "Plaintext length ({len1}) does not match algorithm's expected length ({len2})".format(
                    len1=len(plaintext), len2=algorithm.data_key_len)
                raise DecryptKeyError(error_message)

        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to decrypt data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise DecryptKeyError(error_message)
        return DataKey(
            key_provider=self.key_provider,
            data_key=plaintext,
            encrypted_data_key=encrypted_data_key.encrypted_data_key)
示例#21
0
 def __init__(self, **kwargs):
     self._key_id = to_str(
         self.key_id)  # KMS client requires str, not bytes
     self.config.client.meta.config.user_agent_extra = extend_user_agent_suffix(
         user_agent=self.config.client.meta.config.user_agent_extra,
         suffix=user_agent_suffix)