Просмотр исходного кода

test(authn): add test cases for authn

zhouzb 4 лет назад
Родитель
Сommit
48ddd056b5

+ 90 - 0
apps/emqx_authn/test/emqx_authn_mysql_SUITE.erl

@@ -0,0 +1,90 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_authn_mysql_SUITE).
+
+-compile(nowarn_export_all).
+-compile(export_all).
+
+-include("emqx_authn.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+all() ->
+    emqx_common_test_helpers:all(?MODULE).
+
+groups() ->
+    [].
+
+init_per_suite(Config) ->
+    ok = emqx_common_test_helpers:start_apps([emqx_authn]),
+    Config.
+
+end_per_suite(_Config) ->
+    emqx_common_test_helpers:stop_apps([emqx_authn]),
+    ok.
+
+init_per_testcase(t_authn, Config) ->
+    meck:new(emqx_resource, [non_strict, passthrough, no_history, no_link]),
+    meck:expect(emqx_resource, create_local, fun(_, _, _) -> {ok, undefined} end),
+    Config;
+init_per_testcase(_, Config) ->
+    Config.
+
+end_per_testcase(t_authn, _Config) ->
+    meck:unload(emqx_resource),
+    ok;
+end_per_testcase(_, _Config) ->
+    ok.
+
+%%------------------------------------------------------------------------------
+%% Testcases
+%%------------------------------------------------------------------------------
+
+t_authn(_) ->
+    Password = <<"test">>,
+    Salt = <<"salt">>,
+    PasswordHash = emqx_authn_utils:hash(sha256, Password, Salt, prefix),
+
+    Config = #{<<"mechanism">> => <<"password-based">>,
+               <<"backend">> => <<"mysql">>,
+               <<"server">> => <<"127.0.0.1:3306">>,
+               <<"database">> => <<"mqtt">>,
+               <<"query">> => <<"SELECT password_hash, salt FROM users where username = ${mqtt-username} LIMIT 1">>
+               },
+    {ok, _} = update_config([authentication], {create_authenticator, ?GLOBAL, Config}),
+
+    meck:expect(emqx_resource, query,
+        fun(_, {sql, _, [<<"good">>], _}) ->
+            {ok, [<<"password_hash">>, <<"salt">>], [[PasswordHash, Salt]]};
+           (_, {sql, _, _, _}) ->
+            {error, this_is_a_fictitious_reason}
+        end),
+
+    ClientInfo = #{zone => default,
+                   listener => 'tcp:default',
+                   protocol => mqtt,
+                   username => <<"good">>,
+			       password => Password},
+    ?assertEqual({ok, #{is_superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
+
+    ClientInfo2 = ClientInfo#{username => <<"bad">>},
+    ?assertEqual({error, not_authorized}, emqx_access_control:authenticate(ClientInfo2)),
+
+    ?AUTHN:delete_chain(?GLOBAL).
+
+update_config(Path, ConfigRequest) ->
+    emqx:update_config(Path, ConfigRequest, #{rawconf_with_defaults => true}).
+

+ 101 - 0
apps/emqx_authn/test/emqx_authn_pgsql_SUITE.erl

@@ -0,0 +1,101 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_authn_pgsql_SUITE).
+
+-compile(nowarn_export_all).
+-compile(export_all).
+
+-include("emqx_authn.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
+-include_lib("epgsql/include/epgsql.hrl").
+
+all() ->
+    emqx_common_test_helpers:all(?MODULE).
+
+groups() ->
+    [].
+
+init_per_suite(Config) ->
+    ok = emqx_common_test_helpers:start_apps([emqx_authn]),
+    Config.
+
+end_per_suite(_Config) ->
+    emqx_common_test_helpers:stop_apps([emqx_authn]),
+    ok.
+
+init_per_testcase(t_authn, Config) ->
+    meck:new(emqx_resource, [non_strict, passthrough, no_history, no_link]),
+    meck:expect(emqx_resource, create_local, fun(_, _, _) -> {ok, undefined} end),
+    Config;
+init_per_testcase(_, Config) ->
+    Config.
+
+end_per_testcase(t_authn, _Config) ->
+    meck:unload(emqx_resource),
+    ok;
+end_per_testcase(_, _Config) ->
+    ok.
+
+%%------------------------------------------------------------------------------
+%% Testcases
+%%------------------------------------------------------------------------------
+
+t_parse_query(_) ->
+    Query1 = <<"${mqtt-username}">>,
+    ?assertEqual({<<"$1">>, [<<"${mqtt-username}">>]}, emqx_authn_pgsql:parse_query(Query1)),
+
+    Query2 = <<"${mqtt-username}, ${mqtt-clientid}">>,
+    ?assertEqual({<<"$1, $2">>, [<<"${mqtt-username}">>, <<"${mqtt-clientid}">>]}, emqx_authn_pgsql:parse_query(Query2)),
+
+    Query3 = <<"nomatch">>,
+    ?assertEqual({<<"nomatch">>, []}, emqx_authn_pgsql:parse_query(Query3)).
+
+t_authn(_) ->
+    Password = <<"test">>,
+    Salt = <<"salt">>,
+    PasswordHash = emqx_authn_utils:hash(sha256, Password, Salt, prefix),
+
+    Config = #{<<"mechanism">> => <<"password-based">>,
+               <<"backend">> => <<"postgresql">>,
+               <<"server">> => <<"127.0.0.1:5432">>,
+               <<"database">> => <<"mqtt">>,
+               <<"query">> => <<"SELECT password_hash, salt FROM users where username = ${mqtt-username} LIMIT 1">>
+               },
+    {ok, _} = update_config([authentication], {create_authenticator, ?GLOBAL, Config}),
+
+    meck:expect(emqx_resource, query,
+        fun(_, {sql, _, [<<"good">>]}) ->
+            {ok, [#column{name = <<"password_hash">>}, #column{name = <<"salt">>}], [{PasswordHash, Salt}]};
+           (_, {sql, _, _}) ->
+            {error, this_is_a_fictitious_reason}
+        end),
+
+    ClientInfo = #{zone => default,
+                   listener => 'tcp:default',
+                   protocol => mqtt,
+                   username => <<"good">>,
+			       password => Password},
+    ?assertEqual({ok, #{is_superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
+
+    ClientInfo2 = ClientInfo#{username => <<"bad">>},
+    ?assertEqual({error, not_authorized}, emqx_access_control:authenticate(ClientInfo2)),
+
+    ?AUTHN:delete_chain(?GLOBAL).
+
+update_config(Path, ConfigRequest) ->
+    emqx:update_config(Path, ConfigRequest, #{rawconf_with_defaults => true}).
+