فهرست منبع

chore(acl): support ipaddr list

JianBo He 4 سال پیش
والد
کامیت
07c29e8c55
3فایلهای تغییر یافته به همراه23 افزوده شده و 3 حذف شده
  1. 1 0
      etc/acl.conf
  2. 10 1
      src/emqx_access_rule.erl
  3. 12 2
      test/emqx_access_rule_SUITE.erl

+ 1 - 0
etc/acl.conf

@@ -3,6 +3,7 @@
 %%
 %% -type(who() :: all | binary() |
 %%                {ipaddr, esockd_access:cidr()} |
+%%                {ipaddrs, [esockd_access:cidr()]} |
 %%                {client, binary()} |
 %%                {user, binary()}).
 %%

+ 10 - 1
src/emqx_access_rule.erl

@@ -28,7 +28,8 @@
 -type(who() :: all | binary() |
                {client, binary()} |
                {user, binary()} |
-               {ipaddr, esockd_cidr:cidr_string()}).
+               {ipaddr, esockd_cidr:cidr_string()} |
+               {ipaddrs, list(esockd_cidr:cidr_string())}).
 
 -type(access() :: subscribe | publish | pubsub).
 
@@ -52,6 +53,8 @@ compile(who, all) ->
     all;
 compile(who, {ipaddr, CIDR}) ->
     {ipaddr, esockd_cidr:parse(CIDR, true)};
+compile(who, {ipaddrs, CIDRs}) ->
+    {ipaddrs, lists:map(fun(CIDR) -> esockd_cidr:parse(CIDR, true) end, CIDRs)};
 compile(who, {client, all}) ->
     {client, all};
 compile(who, {client, ClientId}) ->
@@ -107,8 +110,14 @@ match_who(#{username := Username}, {user, Username}) ->
     true;
 match_who(#{peerhost := undefined}, {ipaddr, _Tup}) ->
     false;
+match_who(#{peerhost := undefined}, {ipaddrs, _}) ->
+    false;
 match_who(#{peerhost := IP}, {ipaddr, CIDR}) ->
     esockd_cidr:match(IP, CIDR);
+match_who(#{peerhost := IP}, {ipaddrs, CIDRs}) ->
+    lists:any(fun(CIDR) ->
+        esockd_cidr:match(IP, CIDR)
+    end, CIDRs);
 match_who(ClientInfo, {'and', Conds}) when is_list(Conds) ->
     lists:foldl(fun(Who, Allow) ->
                   match_who(ClientInfo, Who) andalso Allow

+ 12 - 2
test/emqx_access_rule_SUITE.erl

@@ -44,10 +44,18 @@ t_compile(_) ->
     Rule4 = {allow, {'or', [{client, all}, {user, all}]}, pubsub, [ <<"testTopics1">>,  <<"testTopics2">>]},
     Compile4 = {allow, {'or', [{client, all}, {user, all}]}, pubsub, [[<<"testTopics1">>],  [<<"testTopics2">>]]},
 
+    Rule5 = {allow, {ipaddrs, ["127.0.0.1", "192.168.1.0/24"]}, pubsub, <<"%c">>},
+    Compile5 = {allow, {ipaddrs,[{{127,0,0,1},{127,0,0,1},32},
+                                 {{192,168,1,0},{192,168,1,255},24}]},
+                       pubsub,
+                       [{pattern,[<<"%c">>]}]
+               },
+
     ?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)).
+    ?assertEqual(Compile4, emqx_access_rule:compile(Rule4)),
+    ?assertEqual(Compile5, emqx_access_rule:compile(Rule5)).
 
 t_match(_) ->
     ClientInfo1 = #{zone => external,
@@ -94,4 +102,6 @@ t_match(_) ->
     ?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"]}))).
+                                                            emqx_access_rule:compile({allow, {'or', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, ["Topic"]}))),
+    ?assertEqual({matched, allow}, emqx_access_rule:match(ClientInfo2, <<"Topic">>,
+                                                          emqx_access_rule:compile({allow, {ipaddrs, ["127.0.0.1", "192.168.0.0/24"]}, publish, ["Topic"]}))).