From e4e33c2d5d56e87d37335944b3ccac1554ed3340 Mon Sep 17 00:00:00 2001 From: Ery Lee Date: Tue, 31 Mar 2015 21:33:19 +0800 Subject: [PATCH] acl... --- apps/emqttd/src/emqttd_access.erl | 155 ----------- apps/emqttd/src/emqttd_acl.erl | 244 ++++++++++++------ ..._access_tests.erl => emqttd_acl_tests.erl} | 57 ++-- rel/files/acl.config | 4 +- rel/files/app.config | 7 +- 5 files changed, 201 insertions(+), 266 deletions(-) delete mode 100644 apps/emqttd/src/emqttd_access.erl rename apps/emqttd/test/{emqttd_access_tests.erl => emqttd_acl_tests.erl} (52%) diff --git a/apps/emqttd/src/emqttd_access.erl b/apps/emqttd/src/emqttd_access.erl deleted file mode 100644 index 58ae7794a..000000000 --- a/apps/emqttd/src/emqttd_access.erl +++ /dev/null @@ -1,155 +0,0 @@ -%%%----------------------------------------------------------------------------- -%%% @Copyright (C) 2012-2015, Feng Lee -%%% -%%% Permission is hereby granted, free of charge, to any person obtaining a copy -%%% of this software and associated documentation files (the "Software"), to deal -%%% in the Software without restriction, including without limitation the rights -%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -%%% copies of the Software, and to permit persons to whom the Software is -%%% furnished to do so, subject to the following conditions: -%%% -%%% The above copyright notice and this permission notice shall be included in all -%%% copies or substantial portions of the Software. -%%% -%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -%%% SOFTWARE. -%%%----------------------------------------------------------------------------- -%%% @doc -%%% emqttd access rule. -%%% -%%% @end -%%%----------------------------------------------------------------------------- --module(emqttd_access). - --author('feng@emqtt.io'). - --include("emqttd.hrl"). - --export([compile/1, match/3]). - --type pubsub() :: subscribe | publish | pubsub. - --type who() :: all | binary() | - {ipaddr, esockd_access:cidr()} | - {client, binary()} | - {user, binary()}. - --type rule() :: {allow, all} | - {allow, who(), pubsub(), list(binary())} | - {deny, all} | - {deny, who(), pubsub(), list(binary())}. - --define('allow|deny'(A), (A =:= allow) orelse (A =:= deny)). - -%%%----------------------------------------------------------------------------- -%% @doc -%% Compile rule. -%% -%% @end -%%%----------------------------------------------------------------------------- -compile({A, all}) when ?'allow|deny'(A) -> - {A, all}; - -compile({A, Who, PubSub, TopicFilters}) when ?'allow|deny'(A) -> - {A, compile(who, Who), PubSub, [compile(topic, bin(Topic)) || Topic <- TopicFilters]}. - -compile(who, all) -> - all; -compile(who, {ipaddr, CIDR}) -> - {Start, End} = esockd_access:range(CIDR), - {ipaddr, {CIDR, Start, End}}; -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(topic, Topic) -> - Words = emqttd_topic:words(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 rule. -%% -%% @end -%%%----------------------------------------------------------------------------- --spec match(mqtt_user(), binary(), rule()) -> {matched, allow} | {matched, deny} | nomatch. -match(_User, _Topic, {AllowDeny, all}) when ?'allow|deny'(AllowDeny) -> - {matched, AllowDeny}; -match(User, Topic, {AllowDeny, Who, _PubSub, TopicFilters}) - when ?'allow|deny'(AllowDeny) -> - case match_who(User, Who) andalso match_topics(User, Topic, TopicFilters) of - true -> {matched, AllowDeny}; - false -> nomatch - end. - -match_who(_User, all) -> - true; -match_who(_User, {user, all}) -> - true; -match_who(_User, {client, all}) -> - true; -match_who(#mqtt_user{clientid = ClientId}, {client, ClientId}) -> - true; -match_who(#mqtt_user{username = Username}, {user, Username}) -> - true; -match_who(#mqtt_user{ipaddr = IP}, {ipaddr, {_CDIR, Start, End}}) -> - I = esockd_access:atoi(IP), - I >= Start andalso I =< End; -match_who(_User, _Who) -> - false. - -match_topics(_User, _Topic, []) -> - false; -match_topics(User, Topic, [{pattern, PatternFilter}|Filters]) -> - TopicFilter = feed_user(User, PatternFilter), - case match_topic(emqttd_topic:words(Topic), TopicFilter) of - true -> true; - false -> match_topics(User, Topic, Filters) - end; -match_topics(User, Topic, [TopicFilter|Filters]) -> - case match_topic(emqttd_topic:words(Topic), TopicFilter) of - true -> true; - false -> match_topics(User, Topic, Filters) - end. - -match_topic(Topic, TopicFilter) -> - emqttd_topic:match(Topic, TopicFilter). - -feed_user(User, Pattern) -> - feed_user(User, Pattern, []). -feed_user(_User, [], Acc) -> - lists:reverse(Acc); -feed_user(User = #mqtt_user{clientid = undefined}, [<<"$c">>|Words], Acc) -> - feed_user(User, Words, [<<"$c">>|Acc]); -feed_user(User = #mqtt_user{clientid = ClientId}, [<<"$c">>|Words], Acc) -> - feed_user(User, Words, [ClientId |Acc]); -feed_user(User = #mqtt_user{username = undefined}, [<<"$u">>|Words], Acc) -> - feed_user(User, Words, [<<"$u">>|Acc]); -feed_user(User = #mqtt_user{username = Username}, [<<"$u">>|Words], Acc) -> - feed_user(User, Words, [Username|Acc]); -feed_user(User, [W|Words], Acc) -> - feed_user(User, Words, [W|Acc]). - - diff --git a/apps/emqttd/src/emqttd_acl.erl b/apps/emqttd/src/emqttd_acl.erl index 1503ca20b..e0d1d5af4 100644 --- a/apps/emqttd/src/emqttd_acl.erl +++ b/apps/emqttd/src/emqttd_acl.erl @@ -27,8 +27,6 @@ %%% subscribe topic %%% publish to topic %%% -%%% TODO: Support regexp... -%%% %%% @end %%%----------------------------------------------------------------------------- -module(emqttd_acl). @@ -41,30 +39,38 @@ -define(SERVER, ?MODULE). --define(ACL_TAB, mqtt_acl). - %% API Function Exports --export([start_link/0, check/3, allow/3, deny/3]). +-export([start_link/1, check/3, reload/0]). + +-ifdef(TEST). + +-export([compile/1, match/3]). + +-endif. %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --type pubsub() :: publish | subscribe. +-type pubsub() :: subscribe | publish | pubsub. -type who() :: all | binary() | - {clientid, binary()} | - {peername, string() | inet:ip_address()} | - {username, binary()}. + {ipaddr, esockd_access:cidr()} | + {client, binary()} | + {user, binary()}. -type rule() :: {allow, all} | - {allow, who(), binary()} | - {deny, all} | - {deny, who(), binary()}. + {allow, who(), pubsub(), list(binary())} | + {deny, all} | + {deny, who(), pubsub(), list(binary())}. -record(mqtt_acl, {pubsub :: pubsub(), rules :: list(rule())}). +-define(ACL_TAB, mqtt_acl). + +-record(state, {raw_rules = []}). + %%%============================================================================= %%% API %%%============================================================================= @@ -75,19 +81,20 @@ %% %% @end %%------------------------------------------------------------------------------ --spec start_link() -> {ok, pid()} | ignore | {error, any()}. -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). +-spec start_link(AclOpts) -> {ok, pid()} | ignore | {error, any()} when + AclOpts :: [{file, list()}]. +start_link(AclOpts) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [AclOpts], []). --spec check(PubSub, User, Topic) -> allowed | refused when +-spec check(PubSub, User, Topic) -> allow | deny when PubSub :: pubsub(), User :: mqtt_user(), Topic :: binary(). check(PubSub, User, Topic) -> case match(User, Topic, lookup(PubSub)) of - nomatch -> allowed; - allowed -> allowed; - refused -> refused + nomatch -> allow; + {matched, allow} -> allow; + {matched, deny} -> deny end. lookup(PubSub) -> @@ -98,68 +105,46 @@ lookup(PubSub) -> match(_User, _Topic, []) -> nomatch; -match(User, Topic, Rules) -> - %TODO:... - nomatch. --spec allow(PubSub, Who, Topic) -> ok | {error, any()} when - PubSub :: pubsub(), - Who :: who(), - Topic :: binary(). -allow(PubSub, Who, Topic) -> - add_rule(PubSub, {allow, Who, Topic}). - --spec deny(PubSub, Who, Topic) -> ok | {error, any()} when - PubSub :: pubsub(), - Who :: who(), - Topic :: binary(). -deny(PubSub, Who, Topic) -> - add_rule(PubSub, {deny, Who, Topic}). - -add_rule(PubSub, RawRule) -> - case rule(RawRule) of - {error, Error} -> - {error, Error}; - Rule -> - F = fun() -> - case mnesia:wread(?ACL_TAB, PubSub) of - [] -> - mnesia:write(?ACL_TAB, #mqtt_acl{pubsub = PubSub, rules = [Rule]}); - [Rules] -> - mnesia:write(?ACL_TAB, #mqtt_acl{pubsub = PubSub, rules = [Rule|Rules]}) - end - end, - case mnesia:transaction(F) of - {atomic, _} -> ok; - {aborted, Reason} -> {error, {aborted, Reason}} - end +match(User, Topic, [Rule|Rules]) -> + case match_rule(User, Topic, Rule) of + nomatch -> match(User, Topic, Rules); + {matched, AllowDeny} -> {matched, AllowDeny} end. -%% TODO: --spec rule(rule()) -> rule(). -rule({allow, all}) -> - {allow, all}; -rule({allow, Who, Topic}) -> - {allow, Who, Topic}; -rule({deny, Who, Topic}) -> - {deny, Who, Topic}; -rule({deny, all}) -> - {deny, all}. +-spec reload() -> ok. +reload() -> + gen_server:call(?SERVER, reload). %% ------------------------------------------------------------------ %% gen_server Function Definitions %% ------------------------------------------------------------------ -init(Args) -> - mnesia:create_table(?ACL_TAB, [ - {type, set}, - {record_name, mqtt_acl}, - {ram_copies, [node()]}, - {attributes, record_info(fields, mqtt_acl)}]), - mnesia:add_table_copy(?ACL_TAB, node(), ram_copies), - {ok, Args}. +init([AclOpts]) -> + AclFile = proplists:get_value(file, AclOpts), + {ok, Terms} = file:consult(AclFile), + Rules = [compile(Term) || Term <- Terms], + ets:new(?ACL_TAB, [set, protected, named_table, {keypos, 2}]), + lists:foreach(fun(PubSub) -> + ets:insert(?ACL_TAB, #mqtt_acl{pubsub = PubSub, rules = + lists:filter(fun(Rule) -> filter(PubSub, Rule) end, Rules)}) + end, [publish, subscribe]), + {ok, #state{raw_rules = Terms}}. -handle_call(_Request, _From, State) -> - {reply, error, State}. +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. + +handle_call(reload, _From, State) -> + {reply, {error, unsupported}, State}. handle_cast(_Msg, State) -> {noreply, State}. @@ -173,9 +158,114 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%% ------------------------------------------------------------------ -%% Internal Function Definitions -%% ------------------------------------------------------------------ - +%%%============================================================================= +%%% Internal functions +%%%============================================================================= + +%%%----------------------------------------------------------------------------- +%% @doc +%% Compile rule. +%% +%% @end +%%%----------------------------------------------------------------------------- +compile({A, all}) when (A =:= allow) orelse (A =:= deny) -> + {A, all}; + +compile({A, Who, PubSub, TopicFilters}) when (A =:= allow) orelse (A =:= deny) -> + {A, compile(who, Who), PubSub, [compile(topic, bin(Topic)) || Topic <- TopicFilters]}. + +compile(who, all) -> + all; +compile(who, {ipaddr, CIDR}) -> + {Start, End} = esockd_access:range(CIDR), + {ipaddr, {CIDR, Start, End}}; +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(topic, Topic) -> + Words = emqttd_topic:words(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 rule. +%% +%% @end +%%%----------------------------------------------------------------------------- +-spec match_rule(mqtt_user(), binary(), rule()) -> {matched, allow} | {matched, deny} | nomatch. +match_rule(_User, _Topic, {AllowDeny, all}) when (AllowDeny =:= allow) orelse (AllowDeny =:= deny) -> + {matched, AllowDeny}; +match_rule(User, Topic, {AllowDeny, Who, _PubSub, TopicFilters}) + when (AllowDeny =:= allow) orelse (AllowDeny =:= deny) -> + case match_who(User, Who) andalso match_topics(User, Topic, TopicFilters) of + true -> {matched, AllowDeny}; + false -> nomatch + end. + +match_who(_User, all) -> + true; +match_who(_User, {user, all}) -> + true; +match_who(_User, {client, all}) -> + true; +match_who(#mqtt_user{clientid = ClientId}, {client, ClientId}) -> + true; +match_who(#mqtt_user{username = Username}, {user, Username}) -> + true; +match_who(#mqtt_user{ipaddr = IP}, {ipaddr, {_CDIR, Start, End}}) -> + I = esockd_access:atoi(IP), + I >= Start andalso I =< End; +match_who(_User, _Who) -> + false. + +match_topics(_User, _Topic, []) -> + false; +match_topics(User, Topic, [{pattern, PatternFilter}|Filters]) -> + TopicFilter = feed_var(User, PatternFilter), + case match_topic(emqttd_topic:words(Topic), TopicFilter) of + true -> true; + false -> match_topics(User, Topic, Filters) + end; +match_topics(User, Topic, [TopicFilter|Filters]) -> + case match_topic(emqttd_topic:words(Topic), TopicFilter) of + true -> true; + false -> match_topics(User, Topic, Filters) + end. + +match_topic(Topic, TopicFilter) -> + emqttd_topic:match(Topic, TopicFilter). + +feed_var(User, Pattern) -> + feed_var(User, Pattern, []). +feed_var(_User, [], Acc) -> + lists:reverse(Acc); +feed_var(User = #mqtt_user{clientid = undefined}, [<<"$c">>|Words], Acc) -> + feed_var(User, Words, [<<"$c">>|Acc]); +feed_var(User = #mqtt_user{clientid = ClientId}, [<<"$c">>|Words], Acc) -> + feed_var(User, Words, [ClientId |Acc]); +feed_var(User = #mqtt_user{username = undefined}, [<<"$u">>|Words], Acc) -> + feed_var(User, Words, [<<"$u">>|Acc]); +feed_var(User = #mqtt_user{username = Username}, [<<"$u">>|Words], Acc) -> + feed_var(User, Words, [Username|Acc]); +feed_var(User, [W|Words], Acc) -> + feed_var(User, Words, [W|Acc]). diff --git a/apps/emqttd/test/emqttd_access_tests.erl b/apps/emqttd/test/emqttd_acl_tests.erl similarity index 52% rename from apps/emqttd/test/emqttd_access_tests.erl rename to apps/emqttd/test/emqttd_acl_tests.erl index 8e45f172e..22619878c 100644 --- a/apps/emqttd/test/emqttd_access_tests.erl +++ b/apps/emqttd/test/emqttd_acl_tests.erl @@ -20,11 +20,11 @@ %%% SOFTWARE. %%%----------------------------------------------------------------------------- %%% @doc -%%% emqttd_access rules tests. +%%% emqttd_acl tests. %%% %%% @end %%%----------------------------------------------------------------------------- --module(emqttd_access_tests). +-module(emqttd_acl_tests). -include("emqttd.hrl"). @@ -34,43 +34,44 @@ compile_test() -> ?assertMatch({allow, {ipaddr, {"127.0.0.1", _I, _I}}, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]}, - emqttd_access:compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]})), + emqttd_acl:compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]})), ?assertMatch({allow, {user, <<"testuser">>}, subscribe, [ [<<"a">>, <<"b">>, <<"c">>], [<<"d">>, <<"e">>, <<"f">>, '#'] ]}, - emqttd_access:compile({allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]})), + emqttd_acl:compile({allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]})), ?assertEqual({allow, {user, <<"admin">>}, pubsub, [ [<<"d">>, <<"e">>, <<"f">>, '#'] ]}, - emqttd_access:compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})), + emqttd_acl:compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})), ?assertEqual({allow, {client, <<"testClient">>}, publish, [ [<<"testTopics">>, <<"testClient">>] ]}, - emqttd_access:compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})), + emqttd_acl:compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})), ?assertEqual({allow, all, pubsub, [{pattern, [<<"clients">>, <<"$c">>]}]}, - emqttd_access:compile({allow, all, pubsub, ["clients/$c"]})), + emqttd_acl:compile({allow, all, pubsub, ["clients/$c"]})), ?assertEqual({allow, all, subscribe, [{pattern, [<<"users">>, <<"$u">>, '#']}]}, - emqttd_access:compile({allow, all, subscribe, ["users/$u/#"]})), + emqttd_acl:compile({allow, all, subscribe, ["users/$u/#"]})), ?assertEqual({deny, all, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]}, - emqttd_access:compile({deny, all, subscribe, ["$SYS/#", "#"]})), - ?assertEqual({allow, all}, emqttd_access:compile({allow, all})), - ?assertEqual({deny, all}, emqttd_access:compile({deny, all})). + emqttd_acl:compile({deny, all, subscribe, ["$SYS/#", "#"]})), + ?assertEqual({allow, all}, emqttd_acl:compile({allow, all})), + ?assertEqual({deny, all}, emqttd_acl:compile({deny, all})). match_test() -> User = #mqtt_user{ipaddr = {127,0,0,1}, clientid = <<"testClient">>, username = <<"TestUser">>}, User2 = #mqtt_user{ipaddr = {192,168,0,10}, clientid = <<"testClient">>, username = <<"TestUser">>}, - ?assertEqual({matched, allow}, emqttd_access:match(User, <<"Test/Topic">>, {allow, all})), - ?assertEqual({matched, deny}, emqttd_access:match(User, <<"Test/Topic">>, {deny, all})), - ?assertMatch({matched, allow}, emqttd_access:match(User, <<"Test/Topic">>, - emqttd_access:compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}))), - ?assertMatch({matched, allow}, emqttd_access:match(User2, <<"Test/Topic">>, - emqttd_access:compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]}))), - ?assertMatch({matched, allow}, emqttd_access:match(User, <<"d/e/f/x">>, - emqttd_access:compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]}))), - ?assertEqual(nomatch, emqttd_access:match(User, <<"d/e/f/x">>, emqttd_access:compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]}))), - ?assertMatch({matched, allow}, emqttd_access:match(User, <<"testTopics/testClient">>, - emqttd_access:compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]}))), - ?assertMatch({matched, allow}, emqttd_access:match(User, <<"clients/testClient">>, - emqttd_access:compile({allow, all, pubsub, ["clients/$c"]}))), - ?assertMatch({matched, allow}, emqttd_access:match(#mqtt_user{username = <<"user2">>}, <<"users/user2/abc/def">>, - emqttd_access:compile({allow, all, subscribe, ["users/$u/#"]}))), + + ?assertEqual({matched, allow}, emqttd_acl:match(User, <<"Test/Topic">>, [{allow, all}])), + ?assertEqual({matched, deny}, emqttd_acl:match(User, <<"Test/Topic">>, [{deny, all}])), + ?assertMatch({matched, allow}, emqttd_acl:match(User, <<"Test/Topic">>, + emqttd_acl:compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}))), + ?assertMatch({matched, allow}, emqttd_acl:match(User2, <<"Test/Topic">>, + emqttd_acl:compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]}))), + ?assertMatch({matched, allow}, emqttd_acl:match(User, <<"d/e/f/x">>, + emqttd_acl:compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]}))), + ?assertEqual(nomatch, emqttd_acl:match(User, <<"d/e/f/x">>, emqttd_access:compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]}))), + ?assertMatch({matched, allow}, emqttd_acl:match(User, <<"testTopics/testClient">>, + emqttd_acl:compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]}))), + ?assertMatch({matched, allow}, emqttd_acl:match(User, <<"clients/testClient">>, + emqttd_acl:compile({allow, all, pubsub, ["clients/$c"]}))), + ?assertMatch({matched, allow}, emqttd_acl:match(#mqtt_user{username = <<"user2">>}, <<"users/user2/abc/def">>, + emqttd_acl:compile({allow, all, subscribe, ["users/$u/#"]}))), ?assertMatch({matched, deny}, - emqttd_access:match(User, <<"d/e/f">>, - emqttd_access:compile({deny, all, subscribe, ["$SYS/#", "#"]}))). + emqttd_acl:match(User, <<"d/e/f">>, + emqttd_acl:compile({deny, all, subscribe, ["$SYS/#", "#"]}))). -endif. diff --git a/rel/files/acl.config b/rel/files/acl.config index 20cfa0257..e408d1f68 100644 --- a/rel/files/acl.config +++ b/rel/files/acl.config @@ -1,6 +1,3 @@ - - - {allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}. {allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]}. @@ -16,3 +13,4 @@ {deny, all, subscribe, ["$SYS/#", "#"]}. {allow, all}. + diff --git a/rel/files/app.config b/rel/files/app.config index 87299b84a..1ed23e875 100644 --- a/rel/files/app.config +++ b/rel/files/app.config @@ -38,9 +38,10 @@ {logger, {lager, info}} ]}, {emqttd, [ - %Authetication. Internal, Anonymous Default. - {auth, {anonymous, []}}, - {access, []}, + %Authetication. Internal, Anonymous Default + {auth, {anonymous, []}}, + %ACL config + {acl, [{file, "etc/acl.config"}]}, {packet, [ {max_clientid_len, 1024}, {max_packet_size, 16#ffff}