emqx_tls_lib_tests.erl 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_tls_lib_tests).
  17. -include_lib("eunit/include/eunit.hrl").
  18. %% one of the cipher suite from tlsv1.2 and tlsv1.3 each
  19. -define(TLS_12_CIPHER, "ECDHE-ECDSA-AES256-GCM-SHA384").
  20. -define(TLS_13_CIPHER, "TLS_AES_256_GCM_SHA384").
  21. ensure_tls13_ciphers_added_test() ->
  22. Ciphers = emqx_tls_lib:integral_ciphers(['tlsv1.3'], [?TLS_12_CIPHER]),
  23. ?assert(lists:member(?TLS_12_CIPHER, Ciphers)),
  24. ?assert(lists:member(?TLS_13_CIPHER, Ciphers)).
  25. legacy_cipher_suites_test() ->
  26. Ciphers = emqx_tls_lib:integral_ciphers(['tlsv1.2'], [?TLS_12_CIPHER]),
  27. ?assertEqual([?TLS_12_CIPHER], Ciphers).
  28. use_default_ciphers_test() ->
  29. Ciphers = emqx_tls_lib:integral_ciphers(['tlsv1.3', 'tlsv1.2'], ""),
  30. ?assert(lists:member(?TLS_12_CIPHER, Ciphers)),
  31. ?assert(lists:member(?TLS_13_CIPHER, Ciphers)).
  32. ciphers_format_test_() ->
  33. String = ?TLS_13_CIPHER ++ "," ++ ?TLS_12_CIPHER,
  34. Binary = bin(String),
  35. List = [?TLS_13_CIPHER, ?TLS_12_CIPHER],
  36. [ {"string", fun() -> test_cipher_format(String) end}
  37. , {"binary", fun() -> test_cipher_format(Binary) end}
  38. , {"string-list", fun() -> test_cipher_format(List) end}
  39. ].
  40. test_cipher_format(Input) ->
  41. Ciphers = emqx_tls_lib:integral_ciphers(['tlsv1.3', 'tlsv1.2'], Input),
  42. ?assertEqual([?TLS_13_CIPHER, ?TLS_12_CIPHER], Ciphers).
  43. tls_versions_test() ->
  44. ?assert(lists:member('tlsv1.3', emqx_tls_lib:default_versions())).
  45. tls_version_unknown_test() ->
  46. ?assertEqual(emqx_tls_lib:default_versions(),
  47. emqx_tls_lib:integral_versions([])),
  48. ?assertEqual(emqx_tls_lib:default_versions(),
  49. emqx_tls_lib:integral_versions(<<>>)),
  50. ?assertEqual(emqx_tls_lib:default_versions(),
  51. emqx_tls_lib:integral_versions("foo")),
  52. ?assertError(#{reason := no_available_tls_version},
  53. emqx_tls_lib:integral_versions([foo])).
  54. cipher_suites_no_duplication_test() ->
  55. AllCiphers = emqx_tls_lib:default_ciphers(),
  56. ?assertEqual(length(AllCiphers), length(lists:usort(AllCiphers))).
  57. ssl_files_failure_test_() ->
  58. [{"undefined_is_undefined",
  59. fun() ->
  60. ?assertEqual({ok, undefined},
  61. emqx_tls_lib:ensure_ssl_files("dir", undefined)) end},
  62. {"no_op_if_disabled",
  63. fun() ->
  64. Disabled = #{<<"enable">> => false, foo => bar},
  65. ?assertEqual({ok, Disabled},
  66. emqx_tls_lib:ensure_ssl_files("dir", Disabled)) end},
  67. {"enoent_key_file",
  68. fun() ->
  69. NonExistingFile = filename:join("/tmp", integer_to_list(erlang:system_time(microsecond))),
  70. ?assertMatch({error, #{file_read := enoent, pem_check := invalid_pem}},
  71. emqx_tls_lib:ensure_ssl_files("/tmp", #{<<"keyfile">> => NonExistingFile}))
  72. end},
  73. {"bad_pem_string",
  74. fun() ->
  75. %% not valid unicode
  76. ?assertMatch({error, #{reason := invalid_file_path_or_pem_string, which_option := <<"keyfile">>}},
  77. emqx_tls_lib:ensure_ssl_files("/tmp", #{<<"keyfile">> => <<255, 255>>})),
  78. %% not printable
  79. ?assertMatch({error, #{reason := invalid_file_path_or_pem_string}},
  80. emqx_tls_lib:ensure_ssl_files("/tmp", #{<<"keyfile">> => <<33, 22>>})),
  81. TmpFile = filename:join("/tmp", integer_to_list(erlang:system_time(microsecond))),
  82. try
  83. ok = file:write_file(TmpFile, <<"not a valid pem">>),
  84. ?assertMatch({error, #{file_read := not_pem}},
  85. emqx_tls_lib:ensure_ssl_files("/tmp", #{<<"cacertfile">> => bin(TmpFile)}))
  86. after
  87. file:delete(TmpFile)
  88. end
  89. end}
  90. ].
  91. ssl_files_save_delete_test() ->
  92. SSL0 = #{<<"keyfile">> => bin(test_key())},
  93. Dir = filename:join(["/tmp", "ssl-test-dir"]),
  94. {ok, SSL} = emqx_tls_lib:ensure_ssl_files(Dir, SSL0),
  95. File = maps:get(<<"keyfile">>, SSL),
  96. ?assertMatch(<<"/tmp/ssl-test-dir/key-", _:16/binary>>, File),
  97. ?assertEqual({ok, bin(test_key())}, file:read_file(File)),
  98. %% no old file to delete
  99. ok = emqx_tls_lib:delete_ssl_files(Dir, SSL, undefined),
  100. ?assertEqual({ok, bin(test_key())}, file:read_file(File)),
  101. %% old and new identical, no delete
  102. ok = emqx_tls_lib:delete_ssl_files(Dir, SSL, SSL),
  103. ?assertEqual({ok, bin(test_key())}, file:read_file(File)),
  104. %% new is gone, delete old
  105. ok = emqx_tls_lib:delete_ssl_files(Dir, undefined, SSL),
  106. ?assertEqual({error, enoent}, file:read_file(File)),
  107. %% test idempotence
  108. ok = emqx_tls_lib:delete_ssl_files(Dir, undefined, SSL),
  109. ok.
  110. ssl_file_replace_test() ->
  111. SSL0 = #{<<"keyfile">> => bin(test_key())},
  112. SSL1 = #{<<"keyfile">> => bin(test_key2())},
  113. Dir = filename:join(["/tmp", "ssl-test-dir2"]),
  114. {ok, SSL2} = emqx_tls_lib:ensure_ssl_files(Dir, SSL0),
  115. {ok, SSL3} = emqx_tls_lib:ensure_ssl_files(Dir, SSL1),
  116. File1 = maps:get(<<"keyfile">>, SSL2),
  117. File2 = maps:get(<<"keyfile">>, SSL3),
  118. ?assert(filelib:is_regular(File1)),
  119. ?assert(filelib:is_regular(File2)),
  120. %% delete old file (File1, in SSL2)
  121. ok = emqx_tls_lib:delete_ssl_files(Dir, SSL3, SSL2),
  122. ?assertNot(filelib:is_regular(File1)),
  123. ?assert(filelib:is_regular(File2)),
  124. ok.
  125. bin(X) -> iolist_to_binary(X).
  126. test_key() ->
  127. """
  128. -----BEGIN EC PRIVATE KEY-----
  129. MHQCAQEEICKTbbathzvD8zvgjL7qRHhW4alS0+j0Loo7WeYX9AxaoAcGBSuBBAAK
  130. oUQDQgAEJBdF7MIdam5T4YF3JkEyaPKdG64TVWCHwr/plC0QzNVJ67efXwxlVGTo
  131. ju0VBj6tOX1y6C0U+85VOM0UU5xqvw==
  132. -----END EC PRIVATE KEY-----
  133. """.
  134. test_key2() ->
  135. """
  136. -----BEGIN EC PRIVATE KEY-----
  137. MHQCAQEEID9UlIyAlLFw0irkRHX29N+ZGivGtDjlVJvATY3B0TTmoAcGBSuBBAAK
  138. oUQDQgAEUwiarudRNAT25X11js8gE9G+q0GdsT53QJQjRtBO+rTwuCW1vhLzN0Ve
  139. AbToUD4JmV9m/XwcSVH06ZaWqNuC5w==
  140. -----END EC PRIVATE KEY-----
  141. """.