emqx_authn_https_SUITE.erl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2020-2024 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_authn_https_SUITE).
  17. -compile(nowarn_export_all).
  18. -compile(export_all).
  19. -include_lib("emqx_auth/include/emqx_authn.hrl").
  20. -include_lib("eunit/include/eunit.hrl").
  21. -include_lib("common_test/include/ct.hrl").
  22. -include_lib("emqx/include/emqx_placeholder.hrl").
  23. -define(PATH, [?CONF_NS_ATOM]).
  24. -define(HTTPS_PORT, 32334).
  25. -define(HTTPS_PATH, "/auth").
  26. -define(CREDENTIALS, #{
  27. username => <<"plain">>,
  28. password => <<"plain">>,
  29. listener => 'tcp:default',
  30. protocol => mqtt
  31. }).
  32. all() ->
  33. emqx_common_test_helpers:all(?MODULE).
  34. init_per_suite(Config) ->
  35. Apps = emqx_cth_suite:start([cowboy, emqx, emqx_conf, emqx_auth, emqx_auth_http], #{
  36. work_dir => ?config(priv_dir, Config)
  37. }),
  38. [{apps, Apps} | Config].
  39. end_per_suite(Config) ->
  40. emqx_authn_test_lib:delete_authenticators(
  41. [authentication],
  42. ?GLOBAL
  43. ),
  44. ok = emqx_cth_suite:stop(?config(apps, Config)),
  45. ok.
  46. init_per_testcase(_Case, Config) ->
  47. {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000),
  48. emqx_authn_test_lib:delete_authenticators(
  49. [authentication],
  50. ?GLOBAL
  51. ),
  52. {ok, _} = emqx_authn_http_test_server:start_link(?HTTPS_PORT, ?HTTPS_PATH, server_ssl_opts()),
  53. ok = emqx_authn_http_test_server:set_handler(fun cowboy_handler/2),
  54. Config.
  55. end_per_testcase(_Case, _Config) ->
  56. ok = emqx_authn_http_test_server:stop().
  57. %%------------------------------------------------------------------------------
  58. %% Tests
  59. %%------------------------------------------------------------------------------
  60. t_create(_Config) ->
  61. {ok, _} = create_https_auth_with_ssl_opts(
  62. #{
  63. <<"server_name_indication">> => <<"authn-server">>,
  64. <<"verify">> => <<"verify_peer">>,
  65. <<"versions">> => [<<"tlsv1.2">>],
  66. <<"ciphers">> => [<<"ECDHE-RSA-AES256-GCM-SHA384">>]
  67. }
  68. ),
  69. ?assertMatch(
  70. {ok, _},
  71. emqx_access_control:authenticate(?CREDENTIALS)
  72. ).
  73. t_create_invalid_domain(_Config) ->
  74. {ok, _} = create_https_auth_with_ssl_opts(
  75. #{
  76. <<"server_name_indication">> => <<"authn-server-unknown-host">>,
  77. <<"verify">> => <<"verify_peer">>,
  78. <<"versions">> => [<<"tlsv1.2">>],
  79. <<"ciphers">> => [<<"ECDHE-RSA-AES256-GCM-SHA384">>]
  80. }
  81. ),
  82. ?assertEqual(
  83. {error, not_authorized},
  84. emqx_access_control:authenticate(?CREDENTIALS)
  85. ).
  86. t_create_invalid_version(_Config) ->
  87. {ok, _} = create_https_auth_with_ssl_opts(
  88. #{
  89. <<"server_name_indication">> => <<"authn-server">>,
  90. <<"verify">> => <<"verify_peer">>,
  91. <<"versions">> => [<<"tlsv1.1">>]
  92. }
  93. ),
  94. ?assertEqual(
  95. {error, not_authorized},
  96. emqx_access_control:authenticate(?CREDENTIALS)
  97. ).
  98. t_create_invalid_ciphers(_Config) ->
  99. {ok, _} = create_https_auth_with_ssl_opts(
  100. #{
  101. <<"server_name_indication">> => <<"authn-server">>,
  102. <<"verify">> => <<"verify_peer">>,
  103. <<"versions">> => [<<"tlsv1.2">>],
  104. <<"ciphers">> => [<<"ECDHE-ECDSA-AES256-SHA384">>]
  105. }
  106. ),
  107. ?assertEqual(
  108. {error, not_authorized},
  109. emqx_access_control:authenticate(?CREDENTIALS)
  110. ).
  111. %%------------------------------------------------------------------------------
  112. %% Helpers
  113. %%------------------------------------------------------------------------------
  114. create_https_auth_with_ssl_opts(SpecificSSLOpts) ->
  115. AuthConfig = raw_https_auth_config(SpecificSSLOpts),
  116. emqx:update_config(?PATH, {create_authenticator, ?GLOBAL, AuthConfig}).
  117. raw_https_auth_config(SpecificSSLOpts) ->
  118. SSLOpts = maps:merge(
  119. emqx_authn_test_lib:client_ssl_cert_opts(),
  120. #{<<"enable">> => <<"true">>}
  121. ),
  122. #{
  123. <<"mechanism">> => <<"password_based">>,
  124. <<"enable">> => <<"true">>,
  125. <<"backend">> => <<"http">>,
  126. <<"method">> => <<"get">>,
  127. <<"url">> => <<"https://127.0.0.1:32334/auth">>,
  128. <<"body">> => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
  129. <<"headers">> => #{<<"X-Test-Header">> => <<"Test Value">>},
  130. <<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
  131. }.
  132. start_apps(Apps) ->
  133. lists:foreach(fun application:ensure_all_started/1, Apps).
  134. stop_apps(Apps) ->
  135. lists:foreach(fun application:stop/1, Apps).
  136. cert_path(FileName) ->
  137. Dir = code:lib_dir(emqx_auth, test),
  138. filename:join([Dir, <<"data/certs">>, FileName]).
  139. cowboy_handler(Req0, State) ->
  140. Req = cowboy_req:reply(
  141. 200,
  142. #{<<"content-type">> => <<"application/json">>},
  143. emqx_utils_json:encode(#{result => allow, is_superuser => false}),
  144. Req0
  145. ),
  146. {ok, Req, State}.
  147. server_ssl_opts() ->
  148. [
  149. {keyfile, cert_path("server.key")},
  150. {certfile, cert_path("server.crt")},
  151. {cacertfile, cert_path("ca.crt")},
  152. {verify, verify_none},
  153. {versions, ['tlsv1.2', 'tlsv1.3']},
  154. {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384", "TLS_CHACHA20_POLY1305_SHA256"]}
  155. ].