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

Fix reload ACL failed (#2344)

The original `reload_acl` function only parse the ACL file, not compile and rehook to 'client.check_acl'
JianBo He 7 лет назад
Родитель
Сommit
513d2bcaaa
3 измененных файлов с 58 добавлено и 62 удалено
  1. 4 2
      src/emqx_access_control.erl
  2. 13 13
      src/emqx_acl_cache.erl
  3. 41 47
      src/emqx_mod_acl_internal.erl

+ 4 - 2
src/emqx_access_control.erl

@@ -57,12 +57,14 @@ do_check_acl(#{zone := Zone} = Credentials, PubSub, Topic) ->
         _ -> deny
         _ -> deny
     end.
     end.
 
 
--spec(reload_acl() -> list(ok | {error, term()})).
+-spec(reload_acl() -> ok | {error, term()}).
 reload_acl() ->
 reload_acl() ->
+    emqx_acl_cache:is_enabled() andalso
+        emqx_acl_cache:empty_acl_cache(),
     emqx_mod_acl_internal:reload_acl().
     emqx_mod_acl_internal:reload_acl().
 
 
 init_auth_result(Credentials) ->
 init_auth_result(Credentials) ->
     case emqx_zone:get_env(maps:get(zone, Credentials, undefined), allow_anonymous, false) of
     case emqx_zone:get_env(maps:get(zone, Credentials, undefined), allow_anonymous, false) of
         true -> success;
         true -> success;
         false -> not_authorized
         false -> not_authorized
-    end.
+    end.

+ 13 - 13
src/emqx_acl_cache.erl

@@ -16,19 +16,19 @@
 
 
 -include("emqx.hrl").
 -include("emqx.hrl").
 
 
--export([  get_acl_cache/2
-         , put_acl_cache/3
-         , cleanup_acl_cache/0
-         , empty_acl_cache/0
-         , dump_acl_cache/0
-         , get_cache_size/0
-         , get_cache_max_size/0
-         , get_newest_key/0
-         , get_oldest_key/0
-         , cache_k/2
-         , cache_v/1
-         , is_enabled/0
-         ]).
+-export([ get_acl_cache/2
+        , put_acl_cache/3
+        , cleanup_acl_cache/0
+        , empty_acl_cache/0
+        , dump_acl_cache/0
+        , get_cache_size/0
+        , get_cache_max_size/0
+        , get_newest_key/0
+        , get_oldest_key/0
+        , cache_k/2
+        , cache_v/1
+        , is_enabled/0
+        ]).
 
 
 -type(acl_result() :: allow | deny).
 -type(acl_result() :: allow | deny).
 
 

+ 41 - 47
src/emqx_mod_acl_internal.erl

@@ -25,11 +25,9 @@
 
 
 -export([check_acl/5, reload_acl/0]).
 -export([check_acl/5, reload_acl/0]).
 
 
--define(ACL_RULE_TAB, emqx_acl_rule).
+-define(MFA(M, F, A), {M, F, A}).
 
 
--define(FUNC(M, F, A), {M, F, A}).
-
--type(acl_rules() :: #{publish => [emqx_access_rule:rule()],
+-type(acl_rules() :: #{publish   => [emqx_access_rule:rule()],
                        subscribe => [emqx_access_rule:rule()]}).
                        subscribe => [emqx_access_rule:rule()]}).
 
 
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
@@ -37,46 +35,22 @@
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 
 
 load(_Env) ->
 load(_Env) ->
-    Rules = load_rules_from_file(acl_file()),
-    emqx_hooks:add('client.check_acl', ?FUNC(?MODULE, check_acl, [Rules]),  -1).
+    Rules = rules_from_file(acl_file()),
+    emqx_hooks:add('client.check_acl', ?MFA(?MODULE, check_acl, [Rules]),  -1).
 
 
 unload(_Env) ->
 unload(_Env) ->
-    Rules = load_rules_from_file(acl_file()),
-    emqx_hooks:del('client.check_acl', ?FUNC(?MODULE, check_acl, [Rules])).
+    Rules = rules_from_file(acl_file()),
+    emqx_hooks:del('client.check_acl', ?MFA(?MODULE, check_acl, [Rules])).
 
 
 %% @doc Read all rules
 %% @doc Read all rules
 -spec(all_rules() -> list(emqx_access_rule:rule())).
 -spec(all_rules() -> list(emqx_access_rule:rule())).
 all_rules() ->
 all_rules() ->
-    load_rules_from_file(acl_file()).
+    rules_from_file(acl_file()).
 
 
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 %% ACL callbacks
 %% ACL callbacks
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 
 
-load_rules_from_file(AclFile) ->
-    case file:consult(AclFile) of
-        {ok, Terms} ->
-            Rules = [emqx_access_rule:compile(Term) || Term <- Terms],
-            #{publish => lists:filter(fun(Rule) -> filter(publish, Rule) end, Rules),
-              subscribe => lists:filter(fun(Rule) -> filter(subscribe, Rule) end, Rules)};
-        {error, Reason} ->
-            ?LOG(error, "[ACL_INTERNAL] 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.
-
 %% @doc Check ACL
 %% @doc Check ACL
 -spec(check_acl(emqx_types:credentials(), emqx_types:pubsub(), emqx_topic:topic(),
 -spec(check_acl(emqx_types:credentials(), emqx_types:pubsub(), emqx_topic:topic(),
                 emqx_access_rule:acl_result(), acl_rules())
                 emqx_access_rule:acl_result(), acl_rules())
@@ -88,6 +62,17 @@ check_acl(Credentials, PubSub, Topic, _AclResult, Rules) ->
         nomatch          -> ok
         nomatch          -> ok
     end.
     end.
 
 
+-spec(reload_acl() -> ok | {error, term()}).
+reload_acl() ->
+    unload([]), load([]).
+
+%%------------------------------------------------------------------------------
+%% Internal Functions
+%%------------------------------------------------------------------------------
+
+acl_file() ->
+    emqx_config:get_env(acl_file).
+
 lookup(PubSub, Rules) ->
 lookup(PubSub, Rules) ->
     maps:get(PubSub, Rules, []).
     maps:get(PubSub, Rules, []).
 
 
@@ -101,19 +86,28 @@ match(Credentials, Topic, [Rule|Rules]) ->
             {matched, AllowDeny}
             {matched, AllowDeny}
     end.
     end.
 
 
--spec(reload_acl() -> ok | {error, term()}).
-reload_acl() ->
-    try load_rules_from_file(acl_file()) of
-        _ ->
-            emqx_logger:info("Reload acl_file ~s successfully", [acl_file()]),
-            ok;
-        {error, Error} ->
-            {error, Error}
-    catch
-        error:Reason:StackTrace ->
-            ?LOG(error, "Reload acl failed. StackTrace: ~p", [StackTrace]),
-            {error, Reason}
+-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, Reason} ->
+            ?LOG(error, "[ACL_INTERNAL] Failed to read ~s: ~p", [AclFile, Reason]),
+            #{}
     end.
     end.
 
 
-acl_file() ->
-    emqx_config:get_env(acl_file).
+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.
+