summaryrefslogtreecommitdiff
path: root/deps/rabbitmq_cli/test/ctl/encode_command_test.exs
blob: 550e4b24da70cc3f626937f05a16a243c91590f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
## This Source Code Form is subject to the terms of the Mozilla Public
## License, v. 2.0. If a copy of the MPL was not distributed with this
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
##
## Copyright (c) 2007-2020 VMware, Inc. or its affiliates.  All rights reserved.

defmodule EncodeCommandTest do
  use ExUnit.Case, async: false

  @command RabbitMQ.CLI.Ctl.Commands.EncodeCommand

  setup _context do
    {:ok, opts: %{
      cipher: :rabbit_pbe.default_cipher,
      hash: :rabbit_pbe.default_hash,
      iterations: :rabbit_pbe.default_iterations
    }}
  end

  test "validate: providing exactly 2 positional arguments passes", context do
    assert :ok == @command.validate(["value", "secret"], context[:opts])
  end

  test "validate: providing zero or one positional argument fails", context do
    assert match?({:validation_failure, {:not_enough_args, _}},
                  @command.validate([], context[:opts]))
    assert match?({:validation_failure, {:not_enough_args, _}},
                  @command.validate(["value"], context[:opts]))
  end

  test "validate: providing three or more positional argument fails", context do
    assert match?({:validation_failure, :too_many_args},
                  @command.validate(["value", "secret", "incorrect"], context[:opts]))
  end

  test "validate: hash and cipher must be supported", context do
    assert match?(
      {:validation_failure, {:bad_argument, _}},
      @command.validate(["value", "secret"], Map.merge(context[:opts], %{cipher: :funny_cipher}))
    )
    assert match?(
      {:validation_failure, {:bad_argument, _}},
      @command.validate(["value", "secret"], Map.merge(context[:opts], %{hash: :funny_hash}))
    )
    assert match?(
      {:validation_failure, {:bad_argument, _}},
      @command.validate(["value", "secret"], Map.merge(context[:opts], %{cipher: :funny_cipher, hash: :funny_hash}))
    )
    assert :ok == @command.validate(["value", "secret"], context[:opts])
  end

  test "validate: number of iterations must greater than 0", context do
    assert match?(
      {:validation_failure, {:bad_argument, _}},
      @command.validate(["value", "secret"], Map.merge(context[:opts], %{iterations: 0}))
    )
    assert match?(
      {:validation_failure, {:bad_argument, _}},
      @command.validate(["value", "secret"], Map.merge(context[:opts], %{iterations: -1}))
    )
    assert :ok == @command.validate(["value", "secret"], context[:opts])
  end

  test "run: encrypt/decrypt", context do
    # an Erlang list/bitstring
    encrypt_decrypt(to_charlist("foobar"), context)
    # a binary
    encrypt_decrypt("foobar", context)
    # a tuple
    encrypt_decrypt({:password, "secret"}, context)
  end

  defp encrypt_decrypt(secret, context) do
    secret_as_erlang_term = format_as_erlang_term(secret)
    passphrase = "passphrase"

    cipher = context[:opts][:cipher]
    hash = context[:opts][:hash]
    iterations = context[:opts][:iterations]

    {:ok, output} = @command.run([secret_as_erlang_term, passphrase], context[:opts])
    {:encrypted, encrypted} = output
    # decode plain value
    assert secret === :rabbit_pbe.decrypt_term(cipher, hash, iterations, passphrase, {:plaintext, secret})
    # decode {encrypted, ...} tuple form
    assert secret === :rabbit_pbe.decrypt_term(cipher, hash, iterations, passphrase, {:encrypted, encrypted})
  end

  defp format_as_erlang_term(value) do
    :io_lib.format("~p", [value]) |> :lists.flatten() |> to_string()
  end
end