def test_process_cli_request_source_file_destination_file(
        tmpdir, patch_iohandler):
    source = tmpdir.join("source")
    source.write("some data")
    destination = tmpdir.join("destination")

    aws_encryption_sdk_cli.process_cli_request(
        stream_args={"mode": sentinel.mode},
        parsed_args=MagicMock(
            input=str(source),
            output=str(destination),
            recursive=False,
            interactive=sentinel.interactive,
            no_overwrite=sentinel.no_overwrite,
            decode=sentinel.decode_input,
            encode=sentinel.encode_output,
            metadata_output=MetadataWriter(True)(),
            commitment_policy=CommitmentPolicyArgs.
            require_encrypt_require_decrypt,
        ),
    )
    assert not patch_iohandler.return_value.process_dir.called
    assert not patch_iohandler.return_value.process_single_operation.called
    patch_iohandler.return_value.process_single_file.assert_called_once_with(
        stream_args={"mode": sentinel.mode},
        source=str(source),
        destination=str(destination))
def test_process_cli_request_globbed_source_non_directory_target(
        tmpdir, patch_iohandler):
    plaintext_dir = tmpdir.mkdir("plaintext")
    test_file = plaintext_dir.join("testing.aa")
    test_file.write(b"some data here!")
    test_file = plaintext_dir.join("testing.bb")
    test_file.write(b"some data here!")
    ciphertext_dir = tmpdir.mkdir("ciphertext")
    target_file = ciphertext_dir.join("target_file")
    source = os.path.join(str(plaintext_dir), "testing.*")

    with pytest.raises(BadUserArgumentError) as excinfo:
        aws_encryption_sdk_cli.process_cli_request(
            stream_args={"mode": "encrypt"},
            parsed_args=MagicMock(
                commitment_policy=CommitmentPolicyArgs.
                require_encrypt_require_decrypt,
                input=source,
                output=str(target_file),
                recursive=False,
                interactive=False,
                no_overwrite=False,
            ),
        )

    excinfo.match(
        "If operating on multiple sources, destination must be an existing directory"
    )
    assert not patch_iohandler.return_value.process_dir.called
    assert not patch_iohandler.return_value.process_single_file.called
def test_process_cli_request_no_commitment_policy(tmpdir, patch_iohandler):
    source = tmpdir.mkdir("source")
    destination = tmpdir.mkdir("destination")
    metadata_writer = MetadataWriter(True)()
    aws_encryption_sdk_cli.process_cli_request(
        stream_args=sentinel.stream_args,
        parsed_args=MagicMock(
            input=str(source),
            output=str(destination),
            recursive=False,
            interactive=sentinel.interactive,
            no_overwrite=sentinel.no_overwrite,
            metadata_output=metadata_writer,
            decode=sentinel.decode_input,
            encode=sentinel.encode_output,
            encryption_context=sentinel.encryption_context,
            required_encryption_context_keys=sentinel.required_keys,
            commitment_policy=None,
        ),
    )

    patch_iohandler.assert_called_once_with(
        metadata_writer=metadata_writer,
        interactive=sentinel.interactive,
        no_overwrite=sentinel.no_overwrite,
        decode_input=sentinel.decode_input,
        encode_output=sentinel.encode_output,
        required_encryption_context=sentinel.encryption_context,
        required_encryption_context_keys=sentinel.required_keys,
        commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
    )
    assert not patch_iohandler.return_value.process_single_operation.called
    assert not patch_iohandler.return_value.process_dir.called
    assert not patch_iohandler.return_value.process_single_file.called
def test_process_cli_request_source_dir_destination_dir(
        tmpdir, patch_iohandler):
    source = tmpdir.mkdir("source_dir")
    destination = tmpdir.mkdir("destination_dir")
    aws_encryption_sdk_cli.process_cli_request(
        stream_args=sentinel.stream_args,
        parsed_args=MagicMock(
            input=str(source),
            output=str(destination),
            recursive=True,
            interactive=sentinel.interactive,
            no_overwrite=sentinel.no_overwrite,
            suffix=sentinel.suffix,
            decode=sentinel.decode_input,
            encode=sentinel.encode_output,
            metadata_output=MetadataWriter(True)(),
            commitment_policy=CommitmentPolicyArgs.
            require_encrypt_require_decrypt,
        ),
    )

    patch_iohandler.return_value.process_dir.assert_called_once_with(
        stream_args=sentinel.stream_args,
        source=str(source),
        destination=str(destination),
        suffix=sentinel.suffix)
    assert not patch_iohandler.return_value.process_single_file.called
    assert not patch_iohandler.return_value.process_single_operation.called
def test_process_cli_request_source_contains_directory_nonrecursive(tmpdir, patch_iohandler):
    plaintext_dir = tmpdir.mkdir("plaintext")
    test_file_a = plaintext_dir.join("testing.aa")
    test_file_a.write(b"some data here!")
    test_file_c = plaintext_dir.join("testing.cc")
    test_file_c.write(b"some data here!")
    plaintext_dir.mkdir("testing.bb")
    ciphertext_dir = tmpdir.mkdir("ciphertext")
    source = os.path.join(str(plaintext_dir), "testing.*")

    aws_encryption_sdk_cli.process_cli_request(
        stream_args={"mode": "encrypt"},
        parsed_args=MagicMock(
            input=source,
            output=str(ciphertext_dir),
            recursive=False,
            interactive=False,
            no_overwrite=False,
            encode=False,
            decode=False,
            metadata_output=MetadataWriter(True)(),
            commitment_policy=CommitmentPolicyArgs.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
            buffer=False,
        ),
    )

    assert not patch_iohandler.return_value.process_dir.called
    patch_iohandler.return_value.process_single_file.assert_has_calls(
        calls=[
            call(stream_args={"mode": "encrypt"}, source=str(source_file), destination=ANY)
            for source_file in (test_file_a, test_file_c)
        ],
        any_order=True,
    )
def test_process_cli_request_source_stdin_destination_dir(tmpdir):
    with pytest.raises(BadUserArgumentError) as excinfo:
        aws_encryption_sdk_cli.process_cli_request(
            stream_args={"mode": "encrypt"},
            parsed_args=MagicMock(
                input="-", output=str(tmpdir), recursive=False, interactive=False, no_overwrite=False
            ),
        )
    excinfo.match(r"Destination may not be a directory when source is stdin")
def test_process_cli_request_source_is_destination(tmpdir, source_is_symlink, dest_is_symlink, use_files):
    source, dest = build_same_files_and_dirs(tmpdir, source_is_symlink, dest_is_symlink, use_files)

    with pytest.raises(BadUserArgumentError) as excinfo:
        aws_encryption_sdk_cli.process_cli_request(
            stream_args={"mode": "encrypt"},
            parsed_args=MagicMock(input=source, output=dest, recursive=True, interactive=False, no_overwrite=False),
        )
    excinfo.match(r"Destination and source cannot be the same")
Esempio n. 8
0
def parse(raw_args=None):
    """Process input arguments and runs requested operations.

    :param list raw_args: List of arguments
    :returns: parsed arguments
    :rtype: argparse.Namespace
    """
    parser = _build_parser()
    mrcrypt_args = parser.parse_args(raw_args)
    if mrcrypt_args.command is None:
        return parser.format_help()

    try:
        if mrcrypt_args.command == 'encrypt':
            if mrcrypt_args.encryption_context is not None and not isinstance(mrcrypt_args.encryption_context, dict):
                return 'Invalid dictionary in encryption context argument'

        aws_encryption_sdk_cli.setup_logger(
            verbosity=mrcrypt_args.verbose,
            quiet=False
        )

        encryption_cli_args = _transform_args(mrcrypt_args)
        crypto_materials_manager = _build_crypto_materials_manager(encryption_cli_args)
        stream_args = aws_encryption_sdk_cli.stream_kwargs_from_args(encryption_cli_args, crypto_materials_manager)

        aws_encryption_sdk_cli.process_cli_request(
            stream_args=stream_args,
            parsed_args=encryption_cli_args
        )

        # NOTE: If any post-processing of the files created as a result of this operation
        # is desired, the best way to approach this would be to use the output metadata to
        # collect a listing of all written files.
        # http://aws-encryption-sdk-cli.readthedocs.io/en/latest/#output-metadata

        return None
    except AWSEncryptionSDKCLIError as error:
        return error.args[0]
    except Exception as error:  # pylint: disable=broad-except
        message = os.linesep.join([
            'Encountered unexpected error: increase verbosity to see details.',
            '{cls}({args})'.format(
                cls=error.__class__.__name__,
                args=', '.join(['"{}"'.format(arg) for arg in error.args])
            )
        ])
        _LOGGER.debug(message)
        # copy.deepcopy can't handle raw exc_info objects, so format it first
        formatted_traceback = traceback.format_exc()
        _LOGGER.debug(formatted_traceback)
        return message
def test_process_cli_request_source_stdin(tmpdir, patch_iohandler):
    destination = tmpdir.join("destination")
    mock_parsed_args = MagicMock(
        input="-",
        output=str(destination),
        recursive=False,
        interactive=sentinel.interactive,
        no_overwrite=sentinel.no_overwrite,
        decode=sentinel.decode_input,
        encode=sentinel.encode_output,
        metadata_output=MetadataWriter(True)(),
        commitment_policy=CommitmentPolicyArgs.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
        buffer=sentinel.buffer_output,
    )
    aws_encryption_sdk_cli.process_cli_request(stream_args=sentinel.stream_args, parsed_args=mock_parsed_args)
    assert not patch_iohandler.return_value.process_dir.called
    assert not patch_iohandler.return_value.process_single_file.called
    patch_iohandler.return_value.process_single_operation.assert_called_once_with(
        stream_args=sentinel.stream_args, source="-", destination=str(destination)
    )
def test_process_cli_request_invalid_source(tmpdir):
    target = os.path.join(str(tmpdir), "test_targets.*")
    with pytest.raises(BadUserArgumentError) as excinfo:
        aws_encryption_sdk_cli.process_cli_request(
            stream_args={},
            parsed_args=MagicMock(
                input=target,
                output="a specific destination",
                recursive=False,
                interactive=False,
                no_overwrite=False,
                decode=False,
                encode=False,
                metadata_output=MetadataWriter(True)(),
                encryption_context={},
                required_encryption_context_keys=[],
            ),
        )
    excinfo.match(
        r"Invalid source.  Must be a valid pathname pattern or stdin \(-\)")
def test_process_cli_request_source_dir_destination_nondir(tmpdir):
    source = tmpdir.mkdir("source")
    with pytest.raises(BadUserArgumentError) as excinfo:
        aws_encryption_sdk_cli.process_cli_request(
            stream_args={"mode": "encrypt"},
            parsed_args=MagicMock(
                input=str(source),
                output=str(tmpdir.join("destination")),
                recursive=True,
                interactive=False,
                no_overwrite=False,
                decode=False,
                encode=False,
                metadata_output=MetadataWriter(True)(),
                encryption_context={},
                required_encryption_context_keys=[],
            ),
        )
    excinfo.match(
        r"If operating on a source directory, destination must be an existing directory"
    )