Пример #1
0
    def _single_io_write(self, stream_args, source, destination_writer):
        # type: (STREAM_KWARGS, IO, IO) -> OperationResult
        """Performs the actual write operations for a single operation.

        :param dict stream_args: kwargs to pass to `aws_encryption_sdk.stream`
        :param source: source to write
        :type source: file-like object
        :param destination_writer: destination object to which to write
        :type destination_writer: file-like object
        :returns: OperationResult stating whether the file was written
        :rtype: aws_encryption_sdk_cli.internal.identifiers.OperationResult
        """
        with _encoder(source, self.decode_input) as _source, _encoder(
            destination_writer, self.encode_output
        ) as _destination:  # noqa pylint: disable=line-too-long
            with aws_encryption_sdk.stream(source=_source, **stream_args) as handler, self.metadata_writer as metadata:
                metadata_kwargs = dict(
                    mode=stream_args["mode"],
                    input=source.name,
                    output=destination_writer.name,
                    header=json_ready_header(handler.header),
                )
                try:
                    header_auth = handler.header_auth
                except AttributeError:
                    # EncryptStream doesn't expose the header auth at this time
                    pass
                else:
                    metadata_kwargs["header_auth"] = json_ready_header_auth(header_auth)

                if stream_args["mode"] == "decrypt":
                    discovered_ec = handler.header.encryption_context
                    missing_keys = set(self.required_encryption_context_keys).difference(set(discovered_ec.keys()))
                    missing_pairs = set(self.required_encryption_context.items()).difference(set(discovered_ec.items()))
                    if missing_keys or missing_pairs:
                        _LOGGER.warning(
                            "Skipping decrypt because discovered encryption context did not match required elements."
                        )
                        metadata_kwargs.update(
                            dict(
                                skipped=True,
                                reason="Missing encryption context key or value",
                                missing_encryption_context_keys=list(missing_keys),
                                missing_encryption_context_pairs=list(missing_pairs),
                            )
                        )
                        metadata.write_metadata(**metadata_kwargs)
                        return OperationResult.FAILED_VALIDATION

                metadata.write_metadata(**metadata_kwargs)
                for chunk in handler:
                    _destination.write(chunk)
                    _destination.flush()
        return OperationResult.SUCCESS
Пример #2
0
def test_json_ready_message_header():
    # pylint: disable=too-many-locals
    message_id = b"a message ID"
    encryption_context = {"a": "b", "c": "d"}
    content_aad_length = 8
    iv_length = 17
    frame_length = 99
    master_key_provider_id_1 = b"provider 1"
    master_key_provider_info_1 = b"master key 1"
    encrypted_data_key_1 = b"an encrypted data key1"
    master_key_provider_id_2 = b"provider 1"
    master_key_provider_info_2 = b"master key 2"
    encrypted_data_key_2 = b"an encrypted data key2"
    master_key_provider_id_3 = b"another provider"
    master_key_provider_info_3 = b"master key 3"
    encrypted_data_key_3 = b"an encrypted data key3"
    raw_header = MessageHeader(
        version=SerializationVersion.V1,
        type=ObjectType.CUSTOMER_AE_DATA,
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        message_id=message_id,
        encryption_context=encryption_context,
        encrypted_data_keys=set([
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=master_key_provider_id_1,
                    key_info=master_key_provider_info_1),
                encrypted_data_key=encrypted_data_key_1,
            ),
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=master_key_provider_id_2,
                    key_info=master_key_provider_info_2),
                encrypted_data_key=encrypted_data_key_2,
            ),
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=master_key_provider_id_3,
                    key_info=master_key_provider_info_3),
                encrypted_data_key=encrypted_data_key_3,
            ),
        ]),
        content_type=ContentType.FRAMED_DATA,
        content_aad_length=content_aad_length,
        header_iv_length=iv_length,
        frame_length=frame_length,
    )
    expected_header_dict = {
        "version":
        "1.0",
        "type":
        ObjectType.CUSTOMER_AE_DATA.value,
        "commitment_key":
        None,
        "algorithm":
        Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384.name,
        "message_id":
        metadata.unicode_b64_encode(message_id),
        "encryption_context":
        encryption_context,
        "encrypted_data_keys": [
            {
                "key_provider": {
                    "provider_id":
                    metadata.unicode_b64_encode(master_key_provider_id_3),
                    "key_info":
                    metadata.unicode_b64_encode(master_key_provider_info_3),
                },
                "encrypted_data_key":
                metadata.unicode_b64_encode(encrypted_data_key_3),
            },
            {
                "key_provider": {
                    "provider_id":
                    metadata.unicode_b64_encode(master_key_provider_id_1),
                    "key_info":
                    metadata.unicode_b64_encode(master_key_provider_info_1),
                },
                "encrypted_data_key":
                metadata.unicode_b64_encode(encrypted_data_key_1),
            },
            {
                "key_provider": {
                    "provider_id":
                    metadata.unicode_b64_encode(master_key_provider_id_2),
                    "key_info":
                    metadata.unicode_b64_encode(master_key_provider_info_2),
                },
                "encrypted_data_key":
                metadata.unicode_b64_encode(encrypted_data_key_2),
            },
        ],
        "content_type":
        ContentType.FRAMED_DATA.value,
        "header_iv_length":
        iv_length,
        "frame_length":
        frame_length,
    }

    test = metadata.json_ready_header(raw_header)

    assert test == expected_header_dict
    # verify that the dict is actually JSON-encodable
    json.dumps(test)