chore(acl): support ipaddr list

This commit is contained in:
JianBo He 2021-07-27 17:56:09 +08:00
parent dd23ee6b15
commit 07c29e8c55
3 changed files with 23 additions and 3 deletions

View File

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

View File

@ -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

View File

@ -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"]}))).