chore: delete internal acl code
This commit is contained in:
parent
d7c1cf6a5f
commit
1f7291380b
|
@ -1,152 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-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_access_rule).
|
||||
|
||||
%% APIs
|
||||
-export([ match/3
|
||||
, compile/1
|
||||
]).
|
||||
|
||||
-export_type([rule/0]).
|
||||
|
||||
-type(acl_result() :: allow | deny).
|
||||
|
||||
-type(who() :: all | binary() |
|
||||
{client, binary()} |
|
||||
{user, binary()} |
|
||||
{ipaddr, esockd_cidr:cidr_string()}).
|
||||
|
||||
-type(access() :: subscribe | publish | pubsub).
|
||||
|
||||
-type(rule() :: {acl_result(), all} |
|
||||
{acl_result(), who(), access(), list(emqx_topic:topic())}).
|
||||
|
||||
-define(ALLOW_DENY(A), ((A =:= allow) orelse (A =:= deny))).
|
||||
-define(PUBSUB(A), ((A =:= subscribe) orelse (A =:= publish) orelse (A =:= pubsub))).
|
||||
|
||||
%% @doc Compile Access Rule.
|
||||
compile({A, all}) when ?ALLOW_DENY(A) ->
|
||||
{A, all};
|
||||
|
||||
compile({A, Who, Access, Topic}) when ?ALLOW_DENY(A), ?PUBSUB(Access), is_binary(Topic) ->
|
||||
{A, compile(who, Who), Access, [compile(topic, Topic)]};
|
||||
|
||||
compile({A, Who, Access, TopicFilters}) when ?ALLOW_DENY(A), ?PUBSUB(Access) ->
|
||||
{A, compile(who, Who), Access, [compile(topic, Topic) || Topic <- TopicFilters]}.
|
||||
|
||||
compile(who, all) ->
|
||||
all;
|
||||
compile(who, {ipaddr, CIDR}) ->
|
||||
{ipaddr, esockd_cidr:parse(CIDR, true)};
|
||||
compile(who, {client, all}) ->
|
||||
{client, all};
|
||||
compile(who, {client, ClientId}) ->
|
||||
{client, bin(ClientId)};
|
||||
compile(who, {user, all}) ->
|
||||
{user, all};
|
||||
compile(who, {user, Username}) ->
|
||||
{user, bin(Username)};
|
||||
compile(who, {'and', Conds}) when is_list(Conds) ->
|
||||
{'and', [compile(who, Cond) || Cond <- Conds]};
|
||||
compile(who, {'or', Conds}) when is_list(Conds) ->
|
||||
{'or', [compile(who, Cond) || Cond <- Conds]};
|
||||
|
||||
compile(topic, {eq, Topic}) ->
|
||||
{eq, emqx_topic:words(bin(Topic))};
|
||||
compile(topic, Topic) ->
|
||||
Words = emqx_topic:words(bin(Topic)),
|
||||
case pattern(Words) of
|
||||
true -> {pattern, Words};
|
||||
false -> Words
|
||||
end.
|
||||
|
||||
pattern(Words) ->
|
||||
lists:member(<<"%u">>, Words) orelse lists:member(<<"%c">>, Words).
|
||||
|
||||
bin(L) when is_list(L) ->
|
||||
list_to_binary(L);
|
||||
bin(B) when is_binary(B) ->
|
||||
B.
|
||||
|
||||
%% @doc Match access rule
|
||||
-spec(match(emqx_types:clientinfo(), emqx_types:topic(), rule())
|
||||
-> {matched, allow} | {matched, deny} | nomatch).
|
||||
match(_ClientInfo, _Topic, {AllowDeny, all}) when ?ALLOW_DENY(AllowDeny) ->
|
||||
{matched, AllowDeny};
|
||||
match(ClientInfo, Topic, {AllowDeny, Who, _PubSub, TopicFilters})
|
||||
when ?ALLOW_DENY(AllowDeny) ->
|
||||
case match_who(ClientInfo, Who)
|
||||
andalso match_topics(ClientInfo, Topic, TopicFilters) of
|
||||
true -> {matched, AllowDeny};
|
||||
false -> nomatch
|
||||
end.
|
||||
|
||||
match_who(_ClientInfo, all) ->
|
||||
true;
|
||||
match_who(_ClientInfo, {user, all}) ->
|
||||
true;
|
||||
match_who(_ClientInfo, {client, all}) ->
|
||||
true;
|
||||
match_who(#{clientid := ClientId}, {client, ClientId}) ->
|
||||
true;
|
||||
match_who(#{username := Username}, {user, Username}) ->
|
||||
true;
|
||||
match_who(#{peerhost := undefined}, {ipaddr, _Tup}) ->
|
||||
false;
|
||||
match_who(#{peerhost := IP}, {ipaddr, CIDR}) ->
|
||||
esockd_cidr:match(IP, CIDR);
|
||||
match_who(ClientInfo, {'and', Conds}) when is_list(Conds) ->
|
||||
lists:foldl(fun(Who, Allow) ->
|
||||
match_who(ClientInfo, Who) andalso Allow
|
||||
end, true, Conds);
|
||||
match_who(ClientInfo, {'or', Conds}) when is_list(Conds) ->
|
||||
lists:foldl(fun(Who, Allow) ->
|
||||
match_who(ClientInfo, Who) orelse Allow
|
||||
end, false, Conds);
|
||||
match_who(_ClientInfo, _Who) ->
|
||||
false.
|
||||
|
||||
match_topics(_ClientInfo, _Topic, []) ->
|
||||
false;
|
||||
match_topics(ClientInfo, Topic, [{pattern, PatternFilter}|Filters]) ->
|
||||
TopicFilter = feed_var(ClientInfo, PatternFilter),
|
||||
match_topic(emqx_topic:words(Topic), TopicFilter)
|
||||
orelse match_topics(ClientInfo, Topic, Filters);
|
||||
match_topics(ClientInfo, Topic, [TopicFilter|Filters]) ->
|
||||
match_topic(emqx_topic:words(Topic), TopicFilter)
|
||||
orelse match_topics(ClientInfo, Topic, Filters).
|
||||
|
||||
match_topic(Topic, {eq, TopicFilter}) ->
|
||||
Topic == TopicFilter;
|
||||
match_topic(Topic, TopicFilter) ->
|
||||
emqx_topic:match(Topic, TopicFilter).
|
||||
|
||||
feed_var(ClientInfo, Pattern) ->
|
||||
feed_var(ClientInfo, Pattern, []).
|
||||
feed_var(_ClientInfo, [], Acc) ->
|
||||
lists:reverse(Acc);
|
||||
feed_var(ClientInfo = #{clientid := undefined}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(ClientInfo, Words, [<<"%c">>|Acc]);
|
||||
feed_var(ClientInfo = #{clientid := ClientId}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(ClientInfo, Words, [ClientId |Acc]);
|
||||
feed_var(ClientInfo = #{username := undefined}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(ClientInfo, Words, [<<"%u">>|Acc]);
|
||||
feed_var(ClientInfo = #{username := Username}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(ClientInfo, Words, [Username|Acc]);
|
||||
feed_var(ClientInfo, [W|Words], Acc) ->
|
||||
feed_var(ClientInfo, Words, [W|Acc]).
|
||||
|
|
@ -823,8 +823,7 @@ tr_modules(Conf) ->
|
|||
[{emqx_mod_subscription, Subscriptions()}],
|
||||
[{emqx_mod_rewrite, Rewrites()}],
|
||||
[{emqx_mod_topic_metrics, []}],
|
||||
[{emqx_mod_delayed, []}],
|
||||
[{emqx_mod_acl_internal, [{acl_file, conf_get("acl.acl_file", Conf)}]}]
|
||||
[{emqx_mod_delayed, []}]
|
||||
]).
|
||||
|
||||
tr_sysmon(Conf) ->
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
{emqx_mod_acl_internal, true}.
|
||||
{emqx_mod_presence, true}.
|
|
@ -1,15 +0,0 @@
|
|||
{allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}.
|
||||
|
||||
{allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]}.
|
||||
|
||||
{allow, {user, "admin"}, pubsub, ["a/b/c", "d/e/f/#"]}.
|
||||
|
||||
{allow, {client, "testClient"}, subscribe, ["testTopics/testClient"]}.
|
||||
|
||||
{allow, all, subscribe, ["clients/%c"]}.
|
||||
|
||||
{allow, all, pubsub, ["users/%u/#"]}.
|
||||
|
||||
{deny, all, subscribe, ["$SYS/#", "#"]}.
|
||||
|
||||
{deny, all}.
|
|
@ -1,3 +0,0 @@
|
|||
{deny, {user, "emqx"}, pubsub, ["acl_deny_action"]}.
|
||||
{deny, {user, "pub_deny"}, publish, ["pub_deny"]}.
|
||||
{allow, all}.
|
|
@ -1,97 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2019-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_access_rule_SUITE).
|
||||
|
||||
-compile(export_all).
|
||||
-compile(nowarn_export_all).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
all() -> emqx_ct:all(?MODULE).
|
||||
|
||||
init_per_suite(Config) ->
|
||||
emqx_ct_helpers:boot_modules([router, broker]),
|
||||
emqx_ct_helpers:start_apps([]),
|
||||
Config.
|
||||
|
||||
end_per_suite(_Config) ->
|
||||
emqx_ct_helpers:stop_apps([]).
|
||||
|
||||
t_compile(_) ->
|
||||
Rule1 = {allow, all, pubsub, <<"%u">>},
|
||||
Compile1 = {allow, all, pubsub, [{pattern,[<<"%u">>]}]},
|
||||
|
||||
Rule2 = {allow, {ipaddr, "127.0.0.1"}, pubsub, <<"%c">>},
|
||||
Compile2 = {allow, {ipaddr, {{127,0,0,1}, {127,0,0,1}, 32}}, pubsub, [{pattern,[<<"%c">>]}]},
|
||||
|
||||
Rule3 = {allow, {'and', [{client, <<"testClient">>}, {user, <<"testUser">>}]}, pubsub, [<<"testTopics1">>, <<"testTopics2">>]},
|
||||
Compile3 = {allow, {'and', [{client, <<"testClient">>}, {user, <<"testUser">>}]}, pubsub, [[<<"testTopics1">>], [<<"testTopics2">>]]},
|
||||
|
||||
Rule4 = {allow, {'or', [{client, all}, {user, all}]}, pubsub, [ <<"testTopics1">>, <<"testTopics2">>]},
|
||||
Compile4 = {allow, {'or', [{client, all}, {user, all}]}, pubsub, [[<<"testTopics1">>], [<<"testTopics2">>]]},
|
||||
|
||||
?assertEqual(Compile1, emqx_access_rule:compile(Rule1)),
|
||||
?assertEqual(Compile2, emqx_access_rule:compile(Rule2)),
|
||||
?assertEqual(Compile3, emqx_access_rule:compile(Rule3)),
|
||||
?assertEqual(Compile4, emqx_access_rule:compile(Rule4)).
|
||||
|
||||
t_match(_) ->
|
||||
ClientInfo1 = #{zone => external,
|
||||
clientid => <<"testClient">>,
|
||||
username => <<"TestUser">>,
|
||||
peerhost => {127,0,0,1}
|
||||
},
|
||||
ClientInfo2 = #{zone => external,
|
||||
clientid => <<"testClient">>,
|
||||
username => <<"TestUser">>,
|
||||
peerhost => {192,168,0,10}
|
||||
},
|
||||
ClientInfo3 = #{zone => external,
|
||||
clientid => <<"testClient">>,
|
||||
username => <<"TestUser">>,
|
||||
peerhost => undefined
|
||||
},
|
||||
?assertEqual({matched, deny}, emqx_access_rule:match([], [], {deny, all})),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match([], [], {allow, all})),
|
||||
?assertEqual(nomatch, emqx_access_rule:match(ClientInfo1, <<"Test/Topic">>,
|
||||
emqx_access_rule:compile({allow, {user, all}, pubsub, []}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"Test/Topic">>,
|
||||
emqx_access_rule:compile({allow, {client, all}, pubsub, ["$SYS/#", "#"]}))),
|
||||
?assertEqual(nomatch, emqx_access_rule:match(ClientInfo3, <<"Test/Topic">>,
|
||||
emqx_access_rule:compile({allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"Test/Topic">>,
|
||||
emqx_access_rule:compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo2, <<"Test/Topic">>,
|
||||
emqx_access_rule:compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"d/e/f/x">>,
|
||||
emqx_access_rule:compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]}))),
|
||||
?assertEqual(nomatch, emqx_access_rule:match(ClientInfo1, <<"d/e/f/x">>,
|
||||
emqx_access_rule:compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"testTopics/testClient">>,
|
||||
emqx_access_rule:compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"clients/testClient">>,
|
||||
emqx_access_rule:compile({allow, all, pubsub, ["clients/%c"]}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(#{username => <<"user2">>}, <<"users/user2/abc/def">>,
|
||||
emqx_access_rule:compile({allow, all, subscribe, ["users/%u/#"]}))),
|
||||
?assertEqual({matched, deny}, emqx_access_rule:match(ClientInfo1, <<"d/e/f">>,
|
||||
emqx_access_rule:compile({deny, all, subscribe, ["$SYS/#", "#"]}))),
|
||||
?assertEqual(nomatch, emqx_access_rule:match(ClientInfo1, <<"Topic">>,
|
||||
emqx_access_rule:compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, <<"Topic">>}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"Topic">>,
|
||||
emqx_access_rule:compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"TestUser">>}]}, publish, <<"Topic">>}))),
|
||||
?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo1, <<"Topic">>,
|
||||
emqx_access_rule:compile({allow, {'or', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, ["Topic"]}))).
|
|
@ -266,11 +266,18 @@ t_kick_1(_Config) ->
|
|||
|
||||
% mqtt connection kicked by coap with same client id
|
||||
t_acl(Config) ->
|
||||
%% Update acl file and reload mod_acl_internal
|
||||
Path = filename:join([testdir(proplists:get_value(data_dir, Config)), "deny.conf"]),
|
||||
ok = file:write_file(Path, <<"{deny, {user, \"coap\"}, publish, [\"abc\"]}.">>),
|
||||
OldPath = emqx:get_env(acl_file),
|
||||
emqx_mod_acl_internal:reload([{acl_file, Path}]),
|
||||
OldPath = emqx:get_env(plugins_etc_dir),
|
||||
application:set_env(emqx, plugins_etc_dir,
|
||||
emqx_ct_helpers:deps_path(emqx_authz, "test")),
|
||||
Conf = #{<<"authz">> =>
|
||||
#{<<"rules">> =>
|
||||
[#{<<"principal">> =>#{<<"username">> => <<"coap">>},
|
||||
<<"permission">> => deny,
|
||||
<<"topics">> => [<<"abc">>],
|
||||
<<"action">> => <<"publish">>}
|
||||
]}},
|
||||
ok = file:write_file(filename:join(emqx:get_env(plugins_etc_dir), 'authz.conf'), jsx:encode(Conf)),
|
||||
application:ensure_all_started(emqx_authz),
|
||||
|
||||
emqx:subscribe(<<"abc">>),
|
||||
URI = "coap://127.0.0.1/mqtt/adbc?c=client1&u=coap&p=secret",
|
||||
|
@ -282,9 +289,9 @@ t_acl(Config) ->
|
|||
ok
|
||||
end,
|
||||
|
||||
application:set_env(emqx, acl_file, OldPath),
|
||||
file:delete(Path),
|
||||
emqx_mod_acl_internal:reload([{acl_file, OldPath}]).
|
||||
file:delete(filename:join(emqx:get_env(plugins_etc_dir), 'authz.conf')),
|
||||
application:set_env(emqx, plugins_etc_dir, OldPath),
|
||||
application:stop(emqx_authz).
|
||||
|
||||
t_stats(_) ->
|
||||
ok.
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% 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_mod_acl_internal).
|
||||
|
||||
-behaviour(emqx_gen_mod).
|
||||
|
||||
-include_lib("emqx/include/emqx.hrl").
|
||||
-include_lib("emqx/include/logger.hrl").
|
||||
|
||||
-logger_header("[ACL_INTERNAL]").
|
||||
|
||||
%% APIs
|
||||
-export([ check_acl/5
|
||||
, rules_from_file/1
|
||||
]).
|
||||
|
||||
%% emqx_gen_mod callbacks
|
||||
-export([ load/1
|
||||
, unload/1
|
||||
, reload/1
|
||||
, description/0
|
||||
]).
|
||||
|
||||
-type(acl_rules() :: #{publish => [emqx_access_rule:rule()],
|
||||
subscribe => [emqx_access_rule:rule()]}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% API
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
load(Env) ->
|
||||
Rules = rules_from_file(proplists:get_value(acl_file, Env)),
|
||||
emqx_hooks:add('client.check_acl', {?MODULE, check_acl, [Rules]}, -1).
|
||||
|
||||
unload(_Env) ->
|
||||
emqx_hooks:del('client.check_acl', {?MODULE, check_acl}).
|
||||
|
||||
reload(Env) ->
|
||||
emqx_acl_cache:is_enabled() andalso (
|
||||
lists:foreach(
|
||||
fun(Pid) -> erlang:send(Pid, clean_acl_cache) end,
|
||||
emqx_cm:all_channels())),
|
||||
unload(Env), load(Env).
|
||||
|
||||
description() ->
|
||||
"EMQ X Internal ACL Module".
|
||||
%%--------------------------------------------------------------------
|
||||
%% ACL callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc Check ACL
|
||||
-spec(check_acl(emqx_types:clientinfo(), emqx_types:pubsub(), emqx_topic:topic(),
|
||||
emqx_access_rule:acl_result(), acl_rules())
|
||||
-> {ok, allow} | {ok, deny} | ok).
|
||||
check_acl(Client, PubSub, Topic, _AclResult, Rules) ->
|
||||
case match(Client, Topic, lookup(PubSub, Rules)) of
|
||||
{matched, allow} -> {ok, allow};
|
||||
{matched, deny} -> {ok, deny};
|
||||
nomatch -> ok
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal Functions
|
||||
%%--------------------------------------------------------------------
|
||||
lookup(PubSub, Rules) ->
|
||||
maps:get(PubSub, Rules, []).
|
||||
|
||||
match(_Client, _Topic, []) ->
|
||||
nomatch;
|
||||
match(Client, Topic, [Rule|Rules]) ->
|
||||
case emqx_access_rule:match(Client, Topic, Rule) of
|
||||
nomatch ->
|
||||
match(Client, Topic, Rules);
|
||||
{matched, AllowDeny} ->
|
||||
{matched, AllowDeny}
|
||||
end.
|
||||
|
||||
-spec(rules_from_file(file:filename()) -> map()).
|
||||
rules_from_file(AclFile) ->
|
||||
case file:consult(AclFile) of
|
||||
{ok, Terms} ->
|
||||
Rules = [emqx_access_rule:compile(Term) || Term <- Terms],
|
||||
#{publish => [Rule || Rule <- Rules, filter(publish, Rule)],
|
||||
subscribe => [Rule || Rule <- Rules, filter(subscribe, Rule)]};
|
||||
{error, eacces} ->
|
||||
?LOG(alert, "Insufficient permissions to read the ~s file", [AclFile]),
|
||||
#{};
|
||||
{error, enoent} ->
|
||||
?LOG(alert, "The ~s file does not exist", [AclFile]),
|
||||
#{};
|
||||
{error, Reason} ->
|
||||
?LOG(alert, "Failed to read ~s: ~p", [AclFile, Reason]),
|
||||
#{}
|
||||
end.
|
||||
|
||||
filter(_PubSub, {allow, all}) ->
|
||||
true;
|
||||
filter(_PubSub, {deny, all}) ->
|
||||
true;
|
||||
filter(publish, {_AllowDeny, _Who, publish, _Topics}) ->
|
||||
true;
|
||||
filter(_PubSub, {_AllowDeny, _Who, pubsub, _Topics}) ->
|
||||
true;
|
||||
filter(subscribe, {_AllowDeny, _Who, subscribe, _Topics}) ->
|
||||
true;
|
||||
filter(_PubSub, {_AllowDeny, _Who, _, _Topics}) ->
|
||||
false.
|
||||
|
|
@ -80,17 +80,6 @@ unload(ModuleName) ->
|
|||
end.
|
||||
|
||||
-spec(reload(module()) -> ok | ignore | {error, any()}).
|
||||
reload(emqx_mod_acl_internal) ->
|
||||
Modules = emqx:get_env(modules, []),
|
||||
Env = proplists:get_value(emqx_mod_acl_internal, Modules, undefined),
|
||||
case emqx_mod_acl_internal:reload(Env) of
|
||||
ok ->
|
||||
?LOG(info, "Reload ~s module successfully.", [emqx_mod_acl_internal]),
|
||||
ok;
|
||||
{error, Error} ->
|
||||
?LOG(error, "Reload module ~s failed, cannot start for ~0p", [emqx_mod_acl_internal, Error]),
|
||||
{error, Error}
|
||||
end;
|
||||
reload(_) ->
|
||||
ignore.
|
||||
|
||||
|
@ -197,13 +186,6 @@ cli(["unload", Name]) ->
|
|||
emqx_ctl:print("Unload module ~s error: ~p.~n", [Name, Reason])
|
||||
end;
|
||||
|
||||
cli(["reload", "emqx_mod_acl_internal" = Name]) ->
|
||||
case emqx_modules:reload(list_to_atom(Name)) of
|
||||
ok ->
|
||||
emqx_ctl:print("Module ~s reloaded successfully.~n", [Name]);
|
||||
{error, Reason} ->
|
||||
emqx_ctl:print("Reload module ~s error: ~p.~n", [Name, Reason])
|
||||
end;
|
||||
cli(["reload", Name]) ->
|
||||
emqx_ctl:print("Module: ~p does not need to be reloaded.~n", [Name]);
|
||||
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% 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_mod_acl_internal_SUITE).
|
||||
|
||||
-compile(export_all).
|
||||
-compile(nowarn_export_all).
|
||||
|
||||
-include_lib("emqx/include/emqx_mqtt.hrl").
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
all() -> emqx_ct:all(?MODULE).
|
||||
|
||||
init_per_suite(Config) ->
|
||||
emqx_ct_helpers:boot_modules(all),
|
||||
emqx_ct_helpers:start_apps([]),
|
||||
Config.
|
||||
|
||||
end_per_suite(_Config) ->
|
||||
emqx_ct_helpers:stop_apps([]).
|
||||
|
||||
t_load_unload(_) ->
|
||||
?assertEqual(ok, emqx_mod_acl_internal:unload([])),
|
||||
?assertEqual(ok, emqx_mod_acl_internal:load([])),
|
||||
?assertEqual({error,already_exists}, emqx_mod_acl_internal:load([])).
|
||||
|
||||
t_check_acl(_) ->
|
||||
Rules=#{publish => [{allow,all}], subscribe => [{deny, all}]},
|
||||
?assertEqual({ok, allow}, emqx_mod_acl_internal:check_acl(clientinfo(), publish, <<"t">>, [], Rules)),
|
||||
?assertEqual({ok, deny}, emqx_mod_acl_internal:check_acl(clientinfo(), subscribe, <<"t">>, [], Rules)),
|
||||
?assertEqual(ok, emqx_mod_acl_internal:check_acl(clientinfo(), connect, <<"t">>, [], Rules)).
|
||||
|
||||
t_reload_acl(_) ->
|
||||
?assertEqual(ok, emqx_mod_acl_internal:reload([])).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Helper functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
clientinfo() -> clientinfo(#{}).
|
||||
clientinfo(InitProps) ->
|
||||
maps:merge(#{zone => zone,
|
||||
protocol => mqtt,
|
||||
peerhost => {127,0,0,1},
|
||||
clientid => <<"clientid">>,
|
||||
username => <<"username">>,
|
||||
password => <<"passwd">>,
|
||||
is_superuser => false,
|
||||
peercert => undefined,
|
||||
mountpoint => undefined
|
||||
}, InitProps).
|
|
@ -49,8 +49,7 @@ t_load(_) ->
|
|||
?assertEqual(ok, emqx_modules:load()),
|
||||
?assertEqual({error, not_found}, emqx_modules:load(not_existed_module)),
|
||||
?assertEqual({error, not_started}, emqx_modules:unload(emqx_mod_rewrite)),
|
||||
?assertEqual(ignore, emqx_modules:reload(emqx_mod_rewrite)),
|
||||
?assertEqual(ok, emqx_modules:reload(emqx_mod_acl_internal)).
|
||||
?assertEqual(ignore, emqx_modules:reload(emqx_mod_rewrite)).
|
||||
|
||||
t_list(_) ->
|
||||
?assertMatch([{_, _} | _ ], emqx_modules:list()).
|
||||
|
|
|
@ -87,7 +87,6 @@ emqxLoadedPlugins: >
|
|||
{emqx_bridge_mqtt, false}.
|
||||
|
||||
emqxLoadedModules: >
|
||||
{emqx_mod_acl_internal, true}.
|
||||
{emqx_mod_presence, true}.
|
||||
{emqx_mod_delayed, false}.
|
||||
{emqx_mod_rewrite, false}.
|
||||
|
|
|
@ -97,12 +97,11 @@ For example, set mqtt tcp port to 1883
|
|||
|
||||
Default environment variable ``EMQX_LOADED_MODULES``, including
|
||||
|
||||
+ ``emqx_mod_acl_internal``
|
||||
+ ``emqx_mod_presence``
|
||||
|
||||
```bash
|
||||
# The default EMQX_LOADED_MODULES env
|
||||
EMQX_LOADED_MODULES="emqx_mod_acl_internal,emqx_mod_acl_internal"
|
||||
EMQX_LOADED_MODULES="emqx_mod_presence"
|
||||
```
|
||||
|
||||
For example, set ``EMQX_LOADED_MODULES=emqx_mod_delayed,emqx_mod_rewrite`` to load these two modules.
|
||||
|
|
Loading…
Reference in New Issue