chore(authz): add annotations for rules

Signed-off-by: zhanghongtong <rory-z@outlook.com>
This commit is contained in:
zhanghongtong 2021-07-28 09:59:55 +08:00 committed by Rory Z
parent 0ef38c75ed
commit 4ef00072b9
7 changed files with 85 additions and 74 deletions

View File

@ -87,20 +87,16 @@ gen_id(Type) ->
iolist_to_binary([io_lib:format("~s_~s",[?APP, Type]), "_", integer_to_list(erlang:system_time())]). iolist_to_binary([io_lib:format("~s_~s",[?APP, Type]), "_", integer_to_list(erlang:system_time())]).
create_resource(#{type := DB, create_resource(#{type := DB,
config := Config config := Config}) ->
} = Rule) ->
ResourceID = gen_id(DB), ResourceID = gen_id(DB),
case emqx_resource:create( case emqx_resource:create(
ResourceID, ResourceID,
list_to_existing_atom(io_lib:format("~s_~s",[emqx_connector, DB])), list_to_existing_atom(io_lib:format("~s_~s",[emqx_connector, DB])),
Config) Config)
of of
{ok, _} -> {ok, _} -> ResourceID;
Rule#{id => ResourceID}; {error, already_created} -> ResourceID;
{error, already_created} -> {error, Reason} -> {error, Reason}
Rule#{id => ResourceID};
{error, Reason} ->
error({load_config_error, Reason})
end. end.
-spec(init_rule(rule()) -> rule()). -spec(init_rule(rule()) -> rule()).
@ -109,10 +105,10 @@ init_rule(#{topics := Topics,
permission := Permission, permission := Permission,
principal := Principal principal := Principal
} = Rule) when ?ALLOW_DENY(Permission), ?PUBSUB(Action), is_list(Topics) -> } = Rule) when ?ALLOW_DENY(Permission), ?PUBSUB(Action), is_list(Topics) ->
NTopics = [compile_topic(Topic) || Topic <- Topics], Rule#{annotations =>
Rule#{principal => compile_principal(Principal), #{id => gen_id(simple),
topics => NTopics, principal => compile_principal(Principal),
id => gen_id(simple) topics => [compile_topic(Topic) || Topic <- Topics]}
}; };
init_rule(#{principal := Principal, init_rule(#{principal := Principal,
@ -121,16 +117,28 @@ init_rule(#{principal := Principal,
config := #{url := Url} = Config config := #{url := Url} = Config
} = Rule) -> } = Rule) ->
NConfig = maps:merge(Config, #{base_url => maps:remove(query, Url)}), NConfig = maps:merge(Config, #{base_url => maps:remove(query, Url)}),
NRule = create_resource(Rule#{config := NConfig}), case create_resource(Rule#{config := NConfig}) of
NRule#{principal => compile_principal(Principal)}; {error, Reason} -> error({load_config_error, Reason});
Id -> Rule#{annotations =>
#{id => Id,
principal => compile_principal(Principal)
}
}
end;
init_rule(#{principal := Principal, init_rule(#{principal := Principal,
enable := true, enable := true,
type := DB type := DB
} = Rule) when DB =:= redis; } = Rule) when DB =:= redis;
DB =:= mongo -> DB =:= mongo ->
NRule = create_resource(Rule), case create_resource(Rule) of
NRule#{principal => compile_principal(Principal)}; {error, Reason} -> error({load_config_error, Reason});
Id -> Rule#{annotations =>
#{id => Id,
principal => compile_principal(Principal)
}
}
end;
init_rule(#{principal := Principal, init_rule(#{principal := Principal,
enable := true, enable := true,
@ -139,10 +147,16 @@ init_rule(#{principal := Principal,
} = Rule) when DB =:= mysql; } = Rule) when DB =:= mysql;
DB =:= pgsql -> DB =:= pgsql ->
Mod = list_to_existing_atom(io_lib:format("~s_~s",[?APP, DB])), Mod = list_to_existing_atom(io_lib:format("~s_~s",[?APP, DB])),
NRule = create_resource(Rule), case create_resource(Rule) of
NRule#{principal => compile_principal(Principal), {error, Reason} -> error({load_config_error, Reason});
Id -> Rule#{annotations =>
#{id => Id,
principal => compile_principal(Principal),
sql => Mod:parse_query(SQL) sql => Mod:parse_query(SQL)
}; }
}
end;
init_rule(#{enable := false, init_rule(#{enable := false,
type := _DB type := _DB
} = Rule) -> } = Rule) ->
@ -209,9 +223,10 @@ authorize(#{username := Username,
end. end.
do_authorize(Client, PubSub, Topic, do_authorize(Client, PubSub, Topic,
[Connector = #{principal := Principal, [Connector = #{type := DB,
type := DB, enable := true,
enable := true} | Tail] ) -> annotations := #{principal := Principal}
} | Tail] ) ->
case match_principal(Client, Principal) of case match_principal(Client, Principal) of
true -> true ->
Mod = list_to_existing_atom(io_lib:format("~s_~s",[emqx_authz, DB])), Mod = list_to_existing_atom(io_lib:format("~s_~s",[emqx_authz, DB])),
@ -230,9 +245,11 @@ do_authorize(Client, PubSub, Topic,
do_authorize(_Client, _PubSub, _Topic, []) -> nomatch. do_authorize(_Client, _PubSub, _Topic, []) -> nomatch.
match(Client, PubSub, Topic, match(Client, PubSub, Topic,
#{principal := Principal, #{action := Action,
topics := TopicFilters, annotations := #{
action := Action principal := Principal,
topics := TopicFilters
}
}) -> }) ->
match_action(PubSub, Action) andalso match_action(PubSub, Action) andalso
match_principal(Client, Principal) andalso match_principal(Client, Principal) andalso

View File

@ -34,12 +34,12 @@ description() ->
"AuthZ with http". "AuthZ with http".
authorize(Client, PubSub, Topic, authorize(Client, PubSub, Topic,
#{id := ResourceID, #{type := http,
type := http,
config := #{url := #{path := Path} = Url, config := #{url := #{path := Path} = Url,
headers := Headers, headers := Headers,
method := Method, method := Method,
request_timeout := RequestTimeout} = Config request_timeout := RequestTimeout} = Config,
annotations := #{id := ResourceID}
}) -> }) ->
Request = case Method of Request = case Method of
get -> get ->

View File

@ -34,9 +34,9 @@ description() ->
"AuthZ with Mongo". "AuthZ with Mongo".
authorize(Client, PubSub, Topic, authorize(Client, PubSub, Topic,
#{id := ResourceID, #{collection := Collection,
collection := Collection, find := Find,
find := Find annotations := #{id := ResourceID}
}) -> }) ->
case emqx_resource:query(ResourceID, {find, Collection, replvar(Find, Client), #{}}) of case emqx_resource:query(ResourceID, {find, Collection, replvar(Find, Client), #{}}) of
{error, Reason} -> {error, Reason} ->

View File

@ -46,8 +46,9 @@ parse_query(Sql) ->
end. end.
authorize(Client, PubSub, Topic, authorize(Client, PubSub, Topic,
#{id := ResourceID, #{annotations := #{id := ResourceID,
sql := {SQL, Params} sql := {SQL, Params}
}
}) -> }) ->
case emqx_resource:query(ResourceID, {sql, SQL, replvar(Params, Client)}) of case emqx_resource:query(ResourceID, {sql, SQL, replvar(Params, Client)}) of
{ok, _Columns, []} -> nomatch; {ok, _Columns, []} -> nomatch;

View File

@ -50,8 +50,9 @@ parse_query(Sql) ->
end. end.
authorize(Client, PubSub, Topic, authorize(Client, PubSub, Topic,
#{id := ResourceID, #{annotations := #{id := ResourceID,
sql := {SQL, Params} sql := {SQL, Params}
}
}) -> }) ->
case emqx_resource:query(ResourceID, {sql, SQL, replvar(Params, Client)}) of case emqx_resource:query(ResourceID, {sql, SQL, replvar(Params, Client)}) of
{ok, _Columns, []} -> nomatch; {ok, _Columns, []} -> nomatch;

View File

@ -34,8 +34,8 @@ description() ->
"AuthZ with redis". "AuthZ with redis".
authorize(Client, PubSub, Topic, authorize(Client, PubSub, Topic,
#{id := ResourceID, #{cmd := CMD,
cmd := CMD annotations := #{id := ResourceID}
}) -> }) ->
NCMD = string:tokens(replvar(CMD, Client), " "), NCMD = string:tokens(replvar(CMD, Client), " "),
case emqx_resource:query(ResourceID, {cmd, NCMD}) of case emqx_resource:query(ResourceID, {cmd, NCMD}) of

View File

@ -74,35 +74,27 @@ end_per_suite(_Config) ->
%% Testcases %% Testcases
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
t_init_rule(_) -> t_init_rule(_) ->
?assertMatch(#{permission := deny, ?assertMatch(#{annotations := #{id := _ID,
action := all,
principal := all, principal := all,
topics := [['#']], topics := [['#']]}
id := _ID
}, emqx_authz:init_rule(?RULE1)), }, emqx_authz:init_rule(?RULE1)),
?assertMatch(#{permission := allow, ?assertMatch(#{annotations := #{principal :=
action := all,
principal :=
#{ipaddress := {{127,0,0,1},{127,0,0,1},32}}, #{ipaddress := {{127,0,0,1},{127,0,0,1},32}},
topics := [#{eq := ['#']}, topics := [#{eq := ['#']},
#{eq := ['+']}], #{eq := ['+']}],
id := _ID id := _ID}
}, emqx_authz:init_rule(?RULE2)), }, emqx_authz:init_rule(?RULE2)),
?assertMatch( ?assertMatch(#{annotations :=
#{permission := allow, #{principal :=
action := publish,
principal :=
#{'and' := [#{username := {re_pattern, _, _, _, _}}, #{'and' := [#{username := {re_pattern, _, _, _, _}},
#{clientid := {re_pattern, _, _, _, _}} #{clientid := {re_pattern, _, _, _, _}}
] ]
}, },
topics := [[<<"test">>]], topics := [[<<"test">>]],
id := _ID id := _ID}
}, emqx_authz:init_rule(?RULE3)), }, emqx_authz:init_rule(?RULE3)),
?assertMatch( ?assertMatch(#{annotations :=
#{permission := deny, #{principal :=
action := publish,
principal :=
#{'or' := [#{username := {re_pattern, _, _, _, _}}, #{'or' := [#{username := {re_pattern, _, _, _, _}},
#{clientid := {re_pattern, _, _, _, _}} #{clientid := {re_pattern, _, _, _, _}}
] ]
@ -110,7 +102,7 @@ t_init_rule(_) ->
topics := [#{pattern := [<<"%u">>]}, topics := [#{pattern := [<<"%u">>]},
#{pattern := [<<"%c">>]} #{pattern := [<<"%c">>]}
], ],
id := _ID id := _ID}
}, emqx_authz:init_rule(?RULE4)), }, emqx_authz:init_rule(?RULE4)),
ok. ok.