Parcourir la source

chore(authz): test Mria authz

Ilya Averyanov il y a 4 ans
Parent
commit
2bada0bab8

+ 29 - 6
apps/emqx_authz/src/emqx_authz_mnesia.erl

@@ -114,18 +114,19 @@ authorize(#{username := Username,
 %% Management API
 %%--------------------------------------------------------------------
 
+-spec(init_tables() -> ok).
 init_tables() ->
     ok = mria_rlog:wait_for_shards([?ACL_SHARDED], infinity).
 
 -spec(store_rules(who(), rules()) -> ok).
 store_rules({username, Username}, Rules) ->
-    Record = #emqx_acl{who = {?ACL_TABLE_USERNAME, Username}, rules = Rules},
+    Record = #emqx_acl{who = {?ACL_TABLE_USERNAME, Username}, rules = normalize_rules(Rules)},
     mria:dirty_write(Record);
 store_rules({clientid, Clientid}, Rules) ->
-    Record = #emqx_acl{who = {?ACL_TABLE_CLIENTID, Clientid}, rules = Rules},
+    Record = #emqx_acl{who = {?ACL_TABLE_CLIENTID, Clientid}, rules = normalize_rules(Rules)},
     mria:dirty_write(Record);
 store_rules(all, Rules) ->
-    Record = #emqx_acl{who = ?ACL_TABLE_ALL, rules = Rules},
+    Record = #emqx_acl{who = ?ACL_TABLE_ALL, rules = normalize_rules(Rules)},
     mria:dirty_write(Record).
 
 -spec(purge_rules() -> ok).
@@ -176,6 +177,29 @@ record_count() ->
 %% Internal functions
 %%--------------------------------------------------------------------
 
+normalize_rules(Rules) ->
+    lists:map(fun normalize_rule/1, Rules).
+
+normalize_rule({Permission, Action, Topic}) ->
+    {normalize_permission(Permission),
+     normalize_action(Action),
+     normalize_topic(Topic)};
+normalize_rule(Rule) ->
+    error({invalid_rule, Rule}).
+
+normalize_topic(Topic) when is_list(Topic) -> list_to_binary(Topic);
+normalize_topic(Topic) when is_binary(Topic) -> Topic;
+normalize_topic(Topic) -> error({invalid_rule_topic, Topic}).
+
+normalize_action(publish) -> publish;
+normalize_action(subscribe) -> subscribe;
+normalize_action(all) -> all;
+normalize_action(Action) -> error({invalid_rule_action, Action}).
+
+normalize_permission(allow) -> allow;
+normalize_permission(deny) -> deny;
+normalize_permission(Permission) -> error({invalid_rule_permission, Permission}).
+
 do_get_rules(Key) ->
     case mnesia:dirty_read(?ACL_TABLE, Key) of
         [#emqx_acl{rules = Rules}] -> {ok, Rules};
@@ -184,9 +208,8 @@ do_get_rules(Key) ->
 
 do_authorize(_Client, _PubSub, _Topic, []) -> nomatch;
 do_authorize(Client, PubSub, Topic, [ {Permission, Action, TopicFilter} | Tail]) ->
-    case emqx_authz_rule:match(Client, PubSub, Topic,
-                               emqx_authz_rule:compile({Permission, all, Action, [TopicFilter]})
-                              ) of
+    Rule = emqx_authz_rule:compile({Permission, all, Action, [TopicFilter]}),
+    case emqx_authz_rule:match(Client, PubSub, Topic, Rule) of
         {matched, Permission} -> {matched, Permission};
         nomatch -> do_authorize(Client, PubSub, Topic, Tail)
     end.

+ 1 - 1
apps/emqx_authz/test/emqx_authz_file_SUITE.erl

@@ -38,7 +38,7 @@ end_per_suite(_Config) ->
     ok = emqx_authz_test_lib:restore_authorizers(),
     ok = emqx_common_test_helpers:stop_apps([emqx_authz]).
 
-init_per_testcase(Config) ->
+init_per_testcase(_TestCase, Config) ->
     ok = emqx_authz_test_lib:reset_authorizers(),
     Config.
 

+ 107 - 72
apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl

@@ -18,10 +18,8 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_authz.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
--include_lib("emqx/include/emqx_placeholder.hrl").
 
 all() ->
     emqx_common_test_helpers:all(?MODULE).
@@ -31,86 +29,123 @@ groups() ->
 
 init_per_suite(Config) ->
     ok = emqx_common_test_helpers:start_apps(
-           [emqx_connector, emqx_conf, emqx_authz],
-           fun set_special_configs/1
-          ),
+           [emqx_conf, emqx_authz],
+           fun set_special_configs/1),
     Config.
 
 end_per_suite(_Config) ->
-    {ok, _} = emqx:update_config(
-                [authorization],
-                #{<<"no_match">> => <<"allow">>,
-                  <<"cache">> => #{<<"enable">> => <<"true">>},
-                  <<"sources">> => []}),
-    emqx_common_test_helpers:stop_apps([emqx_authz, emqx_conf]),
-    ok.
-
-set_special_configs(emqx_authz) ->
-    {ok, _} = emqx:update_config([authorization, cache, enable], false),
-    {ok, _} = emqx:update_config([authorization, no_match], deny),
-    {ok, _} = emqx:update_config([authorization, sources],
-                                 [#{<<"type">> => <<"built-in-database">>}]),
-    ok;
-set_special_configs(_App) ->
-    ok.
+    ok = emqx_authz_test_lib:restore_authorizers(),
+    ok = emqx_common_test_helpers:stop_apps([emqx_authz]).
 
-init_per_testcase(t_authz, Config) ->
-     emqx_authz_mnesia:store_rules(
-       {username, <<"test_username">>},
-       [{allow, publish, <<"test/", ?PH_S_USERNAME>>},
-        {allow, subscribe, <<"eq #">>}]),
-
-     emqx_authz_mnesia:store_rules(
-       {clientid, <<"test_clientid">>},
-       [{allow, publish, <<"test/", ?PH_S_CLIENTID>>},
-        {deny, subscribe, <<"eq #">>}]),
+init_per_testcase(_TestCase, Config) ->
+    ok = emqx_authz_test_lib:reset_authorizers(),
+    ok = setup_config(),
+    Config.
 
-     emqx_authz_mnesia:store_rules(
-       all,
-       [{deny, all, <<"#">>}]),
+end_per_testcase(_TestCase, _Config) ->
+    ok = emqx_authz_mnesia:purge_rules().
 
-    Config;
-init_per_testcase(_, Config) -> Config.
+set_special_configs(emqx_authz) ->
+    ok = emqx_authz_test_lib:reset_authorizers();
 
-end_per_testcase(t_authz, Config) ->
-    ok = emqx_authz_mnesia:purge_rules(),
-    Config;
-end_per_testcase(_, Config) -> Config.
+set_special_configs(_) ->
+    ok.
 
 %%------------------------------------------------------------------------------
 %% Testcases
 %%------------------------------------------------------------------------------
+t_username_topic_rules(_Config) ->
+    ok = test_topic_rules(username).
+
+t_clientid_topic_rules(_Config) ->
+    ok = test_topic_rules(clientid).
+
+t_all_topic_rules(_Config) ->
+    ok = test_topic_rules(all).
+
+test_topic_rules(Key) ->
+    ClientInfo = #{clientid => <<"clientid">>,
+                   username => <<"username">>,
+                   peerhost => {127,0,0,1},
+                   zone => default,
+                   listener => {tcp, default}
+                  },
+
+    SetupSamples = fun(CInfo, Samples) ->
+                           setup_client_samples(CInfo, Samples, Key)
+                   end,
+
+    ok = emqx_authz_test_lib:test_no_topic_rules(ClientInfo, SetupSamples),
+
+    ok = emqx_authz_test_lib:test_allow_topic_rules(ClientInfo, SetupSamples),
+
+    ok = emqx_authz_test_lib:test_deny_topic_rules(ClientInfo, SetupSamples).
+
+t_normalize_rules(_Config) ->
+    ClientInfo = #{clientid => <<"clientid">>,
+                   username => <<"username">>,
+                   peerhost => {127,0,0,1},
+                   zone => default,
+                   listener => {tcp, default}
+                  },
+
+    ok = emqx_authz_mnesia:store_rules(
+           {username, <<"username">>},
+           [{allow, publish, "t"}]),
+
+    ?assertEqual(
+        allow,
+        emqx_access_control:authorize(ClientInfo, publish, <<"t">>)),
+
+    ?assertException(
+       error,
+       {invalid_rule, _},
+       emqx_authz_mnesia:store_rules(
+         {username, <<"username">>},
+         [[allow, publish, <<"t">>]])),
+
+    ?assertException(
+       error,
+       {invalid_rule_action, _},
+       emqx_authz_mnesia:store_rules(
+         {username, <<"username">>},
+         [{allow, pub, <<"t">>}])),
+
+    ?assertException(
+       error,
+       {invalid_rule_permission, _},
+       emqx_authz_mnesia:store_rules(
+         {username, <<"username">>},
+         [{accept, publish, <<"t">>}])).
 
-t_authz(_) ->
-    ClientInfo1 = #{clientid => <<"test">>,
-                    username => <<"test">>,
-                    peerhost => {127,0,0,1},
-                    listener => {tcp, default}
-                   },
-    ClientInfo2 = #{clientid => <<"fake_clientid">>,
-                    username => <<"test_username">>,
-                    peerhost => {127,0,0,1},
-                    listener => {tcp, default}
-                   },
-    ClientInfo3 = #{clientid => <<"test_clientid">>,
-                    username => <<"fake_username">>,
-                    peerhost => {127,0,0,1},
-                    listener => {tcp, default}
-                   },
-
-    ?assertEqual(deny, emqx_access_control:authorize(
-                         ClientInfo1, subscribe, <<"#">>)),
-    ?assertEqual(deny, emqx_access_control:authorize(
-                         ClientInfo1, publish, <<"#">>)),
-
-    ?assertEqual(allow, emqx_access_control:authorize(
-                          ClientInfo2, publish, <<"test/test_username">>)),
-    ?assertEqual(allow, emqx_access_control:authorize(
-                          ClientInfo2, subscribe, <<"#">>)),
-
-    ?assertEqual(allow, emqx_access_control:authorize(
-                          ClientInfo3, publish, <<"test/test_clientid">>)),
-    ?assertEqual(deny,  emqx_access_control:authorize(
-                          ClientInfo3, subscribe, <<"#">>)),
+%%------------------------------------------------------------------------------
+%% Helpers
+%%------------------------------------------------------------------------------
 
-    ok.
+raw_mnesia_authz_config() ->
+    #{
+        <<"enable">> => <<"true">>,
+        <<"type">> => <<"built-in-database">>
+    }.
+
+setup_client_samples(ClientInfo, Samples, Key) ->
+    ok = emqx_authz_mnesia:purge_rules(),
+    Rules = lists:flatmap(
+           fun(#{topics := Topics, permission := Permission, action := Action}) ->
+                   lists:map(
+                     fun(Topic) ->
+                             {binary_to_atom(Permission), binary_to_atom(Action), Topic}
+                     end,
+                     Topics)
+           end,
+           Samples),
+    #{username := Username, clientid := ClientId} = ClientInfo,
+    Who = case Key of
+              username -> {username, Username};
+              clientid -> {clientid, ClientId};
+              all -> all
+          end,
+    ok = emqx_authz_mnesia:store_rules(Who, Rules).
+
+setup_config() ->
+    emqx_authz_test_lib:setup_config(raw_mnesia_authz_config(), #{}).

+ 1 - 1
apps/emqx_authz/test/emqx_authz_mysql_SUITE.erl

@@ -56,7 +56,7 @@ end_per_suite(_Config) ->
     ok = stop_apps([emqx_resource, emqx_connector]),
     ok = emqx_common_test_helpers:stop_apps([emqx_authz]).
 
-init_per_testcase(Config) ->
+init_per_testcase(_TestCase, Config) ->
     ok = emqx_authz_test_lib:reset_authorizers(),
     Config.
 

+ 1 - 1
apps/emqx_authz/test/emqx_authz_postgresql_SUITE.erl

@@ -56,7 +56,7 @@ end_per_suite(_Config) ->
     ok = stop_apps([emqx_resource, emqx_connector]),
     ok = emqx_common_test_helpers:stop_apps([emqx_authz]).
 
-init_per_testcase(Config) ->
+init_per_testcase(_TestCase, Config) ->
     ok = emqx_authz_test_lib:reset_authorizers(),
     Config.
 

+ 1 - 1
apps/emqx_authz/test/emqx_authz_redis_SUITE.erl

@@ -57,7 +57,7 @@ end_per_suite(_Config) ->
     ok = stop_apps([emqx_resource, emqx_connector]),
     ok = emqx_common_test_helpers:stop_apps([emqx_authz]).
 
-init_per_testcase(Config) ->
+init_per_testcase(_TestCase, Config) ->
     ok = emqx_authz_test_lib:reset_authorizers(),
     Config.
 

+ 1 - 0
apps/emqx_authz/test/emqx_authz_test_lib.erl

@@ -70,6 +70,7 @@ test_samples(ClientInfo, Samples) ->
 test_no_topic_rules(ClientInfo, SetupSamples) ->
     %% No rules
 
+    ok = reset_authorizers(deny, false),
     ok = SetupSamples(ClientInfo, []),
 
     ok = test_samples(