chore: rename check_authz to authorize
This commit is contained in:
parent
c63bdc355a
commit
e1b0f44a8a
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
-export([authenticate/1]).
|
-export([authenticate/1]).
|
||||||
|
|
||||||
-export([ check_authz/3
|
-export([ authorize/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-type(result() :: #{auth_result := emqx_types:auth_result(),
|
-type(result() :: #{auth_result := emqx_types:auth_result(),
|
||||||
|
@ -42,25 +42,25 @@ authenticate(ClientInfo = #{zone := Zone}) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Check ACL
|
%% @doc Check ACL
|
||||||
-spec(check_authz(emqx_types:clientinfo(), emqx_types:pubsub(), emqx_types:topic())
|
-spec(authorize(emqx_types:clientinfo(), emqx_types:pubsub(), emqx_types:topic())
|
||||||
-> allow | deny).
|
-> allow | deny).
|
||||||
check_authz(ClientInfo, PubSub, Topic) ->
|
authorize(ClientInfo, PubSub, Topic) ->
|
||||||
case emqx_acl_cache:is_enabled() of
|
case emqx_acl_cache:is_enabled() of
|
||||||
true -> check_authz_cache(ClientInfo, PubSub, Topic);
|
true -> authorize_cache(ClientInfo, PubSub, Topic);
|
||||||
false -> do_check_authz(ClientInfo, PubSub, Topic)
|
false -> do_authorize(ClientInfo, PubSub, Topic)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_authz_cache(ClientInfo, PubSub, Topic) ->
|
authorize_cache(ClientInfo, PubSub, Topic) ->
|
||||||
case emqx_acl_cache:get_acl_cache(PubSub, Topic) of
|
case emqx_acl_cache:get_acl_cache(PubSub, Topic) of
|
||||||
not_found ->
|
not_found ->
|
||||||
AclResult = do_check_authz(ClientInfo, PubSub, Topic),
|
AclResult = do_authorize(ClientInfo, PubSub, Topic),
|
||||||
emqx_acl_cache:put_acl_cache(PubSub, Topic, AclResult),
|
emqx_acl_cache:put_acl_cache(PubSub, Topic, AclResult),
|
||||||
AclResult;
|
AclResult;
|
||||||
AclResult -> AclResult
|
AclResult -> AclResult
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_check_authz(ClientInfo, PubSub, Topic) ->
|
do_authorize(ClientInfo, PubSub, Topic) ->
|
||||||
case run_hooks('client.check_authz', [ClientInfo, PubSub, Topic], allow) of
|
case run_hooks('client.authorize', [ClientInfo, PubSub, Topic], allow) of
|
||||||
allow -> allow;
|
allow -> allow;
|
||||||
_Other -> deny
|
_Other -> deny
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -1406,7 +1406,7 @@ check_pub_alias(_Packet, _Channel) -> ok.
|
||||||
check_pub_acl(#mqtt_packet{variable = #mqtt_packet_publish{topic_name = Topic}},
|
check_pub_acl(#mqtt_packet{variable = #mqtt_packet_publish{topic_name = Topic}},
|
||||||
#channel{clientinfo = ClientInfo}) ->
|
#channel{clientinfo = ClientInfo}) ->
|
||||||
case is_acl_enabled(ClientInfo) andalso
|
case is_acl_enabled(ClientInfo) andalso
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, Topic) of
|
emqx_access_control:authorize(ClientInfo, publish, Topic) of
|
||||||
false -> ok;
|
false -> ok;
|
||||||
allow -> ok;
|
allow -> ok;
|
||||||
deny -> {error, ?RC_NOT_AUTHORIZED}
|
deny -> {error, ?RC_NOT_AUTHORIZED}
|
||||||
|
@ -1440,7 +1440,7 @@ check_sub_acls([], _Channel, Acc) ->
|
||||||
|
|
||||||
check_sub_acl(TopicFilter, #channel{clientinfo = ClientInfo}) ->
|
check_sub_acl(TopicFilter, #channel{clientinfo = ClientInfo}) ->
|
||||||
case is_acl_enabled(ClientInfo) andalso
|
case is_acl_enabled(ClientInfo) andalso
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, TopicFilter) of
|
emqx_access_control:authorize(ClientInfo, subscribe, TopicFilter) of
|
||||||
false -> allow;
|
false -> allow;
|
||||||
Result -> Result
|
Result -> Result
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -172,7 +172,7 @@
|
||||||
{counter, 'client.connected'},
|
{counter, 'client.connected'},
|
||||||
{counter, 'client.authenticate'},
|
{counter, 'client.authenticate'},
|
||||||
{counter, 'client.auth.anonymous'},
|
{counter, 'client.auth.anonymous'},
|
||||||
{counter, 'client.check_authz'},
|
{counter, 'client.authorize'},
|
||||||
{counter, 'client.subscribe'},
|
{counter, 'client.subscribe'},
|
||||||
{counter, 'client.unsubscribe'},
|
{counter, 'client.unsubscribe'},
|
||||||
{counter, 'client.disconnected'}
|
{counter, 'client.disconnected'}
|
||||||
|
@ -563,7 +563,7 @@ reserved_idx('client.connected') -> 202;
|
||||||
reserved_idx('client.authenticate') -> 203;
|
reserved_idx('client.authenticate') -> 203;
|
||||||
reserved_idx('client.enhanced_authenticate') -> 204;
|
reserved_idx('client.enhanced_authenticate') -> 204;
|
||||||
reserved_idx('client.auth.anonymous') -> 205;
|
reserved_idx('client.auth.anonymous') -> 205;
|
||||||
reserved_idx('client.check_authz') -> 206;
|
reserved_idx('client.authorize') -> 206;
|
||||||
reserved_idx('client.subscribe') -> 207;
|
reserved_idx('client.subscribe') -> 207;
|
||||||
reserved_idx('client.unsubscribe') -> 208;
|
reserved_idx('client.unsubscribe') -> 208;
|
||||||
reserved_idx('client.disconnected') -> 209;
|
reserved_idx('client.disconnected') -> 209;
|
||||||
|
|
|
@ -38,9 +38,9 @@ t_authenticate(_) ->
|
||||||
emqx_zone:set_env(zone, allow_anonymous, true),
|
emqx_zone:set_env(zone, allow_anonymous, true),
|
||||||
?assertMatch({ok, _}, emqx_access_control:authenticate(clientinfo())).
|
?assertMatch({ok, _}, emqx_access_control:authenticate(clientinfo())).
|
||||||
|
|
||||||
t_check_authz(_) ->
|
t_authorize(_) ->
|
||||||
Publish = ?PUBLISH_PACKET(?QOS_0, <<"t">>, 1, <<"payload">>),
|
Publish = ?PUBLISH_PACKET(?QOS_0, <<"t">>, 1, <<"payload">>),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(clientinfo(), Publish, <<"t">>)).
|
?assertEqual(allow, emqx_access_control:authorize(clientinfo(), Publish, <<"t">>)).
|
||||||
|
|
||||||
t_bypass_auth_plugins(_) ->
|
t_bypass_auth_plugins(_) ->
|
||||||
ClientInfo = clientinfo(),
|
ClientInfo = clientinfo(),
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
|
|
||||||
%% ACL callbacks
|
%% ACL callbacks
|
||||||
-export([ init/1
|
-export([ init/1
|
||||||
, check_authz/2
|
, authorize/2
|
||||||
, description/0
|
, description/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
init(AclOpts) ->
|
init(AclOpts) ->
|
||||||
{ok, AclOpts}.
|
{ok, AclOpts}.
|
||||||
|
|
||||||
check_authz({_User, _PubSub, _Topic}, _State) ->
|
authorize({_User, _PubSub, _Topic}, _State) ->
|
||||||
allow.
|
allow.
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -37,7 +37,7 @@ init_per_suite(Config) ->
|
||||||
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
||||||
ok = meck:expect(emqx_access_control, authenticate,
|
ok = meck:expect(emqx_access_control, authenticate,
|
||||||
fun(_) -> {ok, #{auth_result => success}} end),
|
fun(_) -> {ok, #{auth_result => success}} end),
|
||||||
ok = meck:expect(emqx_access_control, check_authz, fun(_, _, _) -> allow end),
|
ok = meck:expect(emqx_access_control, authorize, fun(_, _, _) -> allow end),
|
||||||
%% Broker Meck
|
%% Broker Meck
|
||||||
ok = meck:new(emqx_broker, [passthrough, no_history, no_link]),
|
ok = meck:new(emqx_broker, [passthrough, no_history, no_link]),
|
||||||
%% Hooks Meck
|
%% Hooks Meck
|
||||||
|
|
|
@ -198,7 +198,7 @@ t_batch_subscribe(_) ->
|
||||||
{ok, Client} = emqtt:start_link([{proto_ver, v5}, {clientid, <<"batch_test">>}]),
|
{ok, Client} = emqtt:start_link([{proto_ver, v5}, {clientid, <<"batch_test">>}]),
|
||||||
{ok, _} = emqtt:connect(Client),
|
{ok, _} = emqtt:connect(Client),
|
||||||
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history, no_link]),
|
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history, no_link]),
|
||||||
meck:expect(emqx_access_control, check_authz, fun(_, _, _) -> deny end),
|
meck:expect(emqx_access_control, authorize, fun(_, _, _) -> deny end),
|
||||||
{ok, _, [?RC_NOT_AUTHORIZED,
|
{ok, _, [?RC_NOT_AUTHORIZED,
|
||||||
?RC_NOT_AUTHORIZED,
|
?RC_NOT_AUTHORIZED,
|
||||||
?RC_NOT_AUTHORIZED]} = emqtt:subscribe(Client, [{<<"t1">>, qos1},
|
?RC_NOT_AUTHORIZED]} = emqtt:subscribe(Client, [{<<"t1">>, qos1},
|
||||||
|
|
|
@ -64,7 +64,7 @@ init_per_testcase(TestCase, Config) when
|
||||||
end),
|
end),
|
||||||
%% Mock emqx_access_control
|
%% Mock emqx_access_control
|
||||||
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
||||||
ok = meck:expect(emqx_access_control, check_authz, fun(_, _, _) -> allow end),
|
ok = meck:expect(emqx_access_control, authorize, fun(_, _, _) -> allow end),
|
||||||
%% Mock emqx_hooks
|
%% Mock emqx_hooks
|
||||||
ok = meck:new(emqx_hooks, [passthrough, no_history, no_link]),
|
ok = meck:new(emqx_hooks, [passthrough, no_history, no_link]),
|
||||||
ok = meck:expect(emqx_hooks, run, fun(_Hook, _Args) -> ok end),
|
ok = meck:expect(emqx_hooks, run, fun(_Hook, _Args) -> ok end),
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
, compile/1
|
, compile/1
|
||||||
, lookup/0
|
, lookup/0
|
||||||
, update/1
|
, update/1
|
||||||
, check_authz/5
|
, authorize/5
|
||||||
, match/4
|
, match/4
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ init() ->
|
||||||
#{<<"authz">> := #{<<"rules">> := Rules}} = hocon_schema:check_plain(emqx_authz_schema, RawConf),
|
#{<<"authz">> := #{<<"rules">> := Rules}} = hocon_schema:check_plain(emqx_authz_schema, RawConf),
|
||||||
ok = application:set_env(?APP, rules, Rules),
|
ok = application:set_env(?APP, rules, Rules),
|
||||||
NRules = [compile(Rule) || Rule <- Rules],
|
NRules = [compile(Rule) || Rule <- Rules],
|
||||||
ok = emqx_hooks:add('client.check_authz', {?MODULE, check_authz, [NRules]}, -1).
|
ok = emqx_hooks:add('client.authorize', {?MODULE, authorize, [NRules]}, -1).
|
||||||
|
|
||||||
lookup() ->
|
lookup() ->
|
||||||
application:get_env(?APP, rules, []).
|
application:get_env(?APP, rules, []).
|
||||||
|
@ -50,8 +50,8 @@ update(Rules) ->
|
||||||
ok = application:set_env(?APP, rules, Rules),
|
ok = application:set_env(?APP, rules, Rules),
|
||||||
NRules = [compile(Rule) || Rule <- Rules],
|
NRules = [compile(Rule) || Rule <- Rules],
|
||||||
Action = find_action_in_hooks(),
|
Action = find_action_in_hooks(),
|
||||||
ok = emqx_hooks:del('client.check_authz', Action),
|
ok = emqx_hooks:del('client.authorize', Action),
|
||||||
ok = emqx_hooks:add('client.check_authz', {?MODULE, check_authz, [NRules]}, -1),
|
ok = emqx_hooks:add('client.authorize', {?MODULE, authorize, [NRules]}, -1),
|
||||||
ok = emqx_acl_cache:empty_acl_cache().
|
ok = emqx_acl_cache:empty_acl_cache().
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -59,8 +59,8 @@ update(Rules) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
find_action_in_hooks() ->
|
find_action_in_hooks() ->
|
||||||
Callbacks = emqx_hooks:lookup('client.check_authz'),
|
Callbacks = emqx_hooks:lookup('client.authorize'),
|
||||||
[Action] = [Action || {callback,{?MODULE, check_authz, _} = Action, _, _} <- Callbacks ],
|
[Action] = [Action || {callback,{?MODULE, authorize, _} = Action, _, _} <- Callbacks ],
|
||||||
Action.
|
Action.
|
||||||
|
|
||||||
create_resource(#{<<"type">> := DB,
|
create_resource(#{<<"type">> := DB,
|
||||||
|
@ -149,12 +149,12 @@ b2l(B) when is_binary(B) -> binary_to_list(B).
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
%% @doc Check ACL
|
%% @doc Check ACL
|
||||||
-spec(check_authz(emqx_types:clientinfo(), emqx_types:all(), emqx_topic:topic(), emqx_permission_rule:acl_result(), rules())
|
-spec(authorize(emqx_types:clientinfo(), emqx_types:all(), emqx_topic:topic(), emqx_permission_rule:acl_result(), rules())
|
||||||
-> {stop, allow} | {ok, deny}).
|
-> {stop, allow} | {ok, deny}).
|
||||||
check_authz(#{username := Username,
|
authorize(#{username := Username,
|
||||||
peerhost := IpAddress
|
peerhost := IpAddress
|
||||||
} = Client, PubSub, Topic, _DefaultResult, Rules) ->
|
} = Client, PubSub, Topic, _DefaultResult, Rules) ->
|
||||||
case do_check_authz(Client, PubSub, Topic, Rules) of
|
case do_authorize(Client, PubSub, Topic, Rules) of
|
||||||
{matched, allow} ->
|
{matched, allow} ->
|
||||||
?LOG(info, "Client succeeded authorization: Username: ~p, IP: ~p, Topic: ~p, Permission: allow", [Username, IpAddress, Topic]),
|
?LOG(info, "Client succeeded authorization: Username: ~p, IP: ~p, Topic: ~p, Permission: allow", [Username, IpAddress, Topic]),
|
||||||
emqx_metrics:inc(?ACL_METRICS(allow)),
|
emqx_metrics:inc(?ACL_METRICS(allow)),
|
||||||
|
@ -168,25 +168,25 @@ check_authz(#{username := Username,
|
||||||
{stop, deny}
|
{stop, deny}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_check_authz(Client, PubSub, Topic,
|
do_authorize(Client, PubSub, Topic,
|
||||||
[Connector = #{<<"principal">> := Principal,
|
[Connector = #{<<"principal">> := Principal,
|
||||||
<<"type">> := DB} | Tail] ) ->
|
<<"type">> := DB} | 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])),
|
||||||
case Mod:check_authz(Client, PubSub, Topic, Connector) of
|
case Mod:authorize(Client, PubSub, Topic, Connector) of
|
||||||
nomatch -> do_check_authz(Client, PubSub, Topic, Tail);
|
nomatch -> do_authorize(Client, PubSub, Topic, Tail);
|
||||||
Matched -> Matched
|
Matched -> Matched
|
||||||
end;
|
end;
|
||||||
false -> do_check_authz(Client, PubSub, Topic, Tail)
|
false -> do_authorize(Client, PubSub, Topic, Tail)
|
||||||
end;
|
end;
|
||||||
do_check_authz(Client, PubSub, Topic,
|
do_authorize(Client, PubSub, Topic,
|
||||||
[#{<<"permission">> := Permission} = Rule | Tail]) ->
|
[#{<<"permission">> := Permission} = Rule | Tail]) ->
|
||||||
case match(Client, PubSub, Topic, Rule) of
|
case match(Client, PubSub, Topic, Rule) of
|
||||||
true -> {matched, Permission};
|
true -> {matched, Permission};
|
||||||
false -> do_check_authz(Client, PubSub, Topic, Tail)
|
false -> do_authorize(Client, PubSub, Topic, Tail)
|
||||||
end;
|
end;
|
||||||
do_check_authz(_Client, _PubSub, _Topic, []) -> nomatch.
|
do_authorize(_Client, _PubSub, _Topic, []) -> nomatch.
|
||||||
|
|
||||||
match(Client, PubSub, Topic,
|
match(Client, PubSub, Topic,
|
||||||
#{<<"principal">> := Principal,
|
#{<<"principal">> := Principal,
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
%% ACL Callbacks
|
%% ACL Callbacks
|
||||||
-export([ description/0
|
-export([ description/0
|
||||||
, parse_query/1
|
, parse_query/1
|
||||||
, check_authz/4
|
, authorize/4
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
|
@ -45,25 +45,25 @@ parse_query(Sql) ->
|
||||||
{Sql, []}
|
{Sql, []}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_authz(Client, PubSub, Topic,
|
authorize(Client, PubSub, Topic,
|
||||||
#{<<"resource_id">> := ResourceID,
|
#{<<"resource_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;
|
||||||
{ok, Columns, Rows} ->
|
{ok, Columns, Rows} ->
|
||||||
do_check_authz(Client, PubSub, Topic, Columns, Rows);
|
do_authorize(Client, PubSub, Topic, Columns, Rows);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?LOG(error, "[AuthZ] Query mysql error: ~p~n", [Reason]),
|
?LOG(error, "[AuthZ] Query mysql error: ~p~n", [Reason]),
|
||||||
nomatch
|
nomatch
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_check_authz(_Client, _PubSub, _Topic, _Columns, []) ->
|
do_authorize(_Client, _PubSub, _Topic, _Columns, []) ->
|
||||||
nomatch;
|
nomatch;
|
||||||
do_check_authz(Client, PubSub, Topic, Columns, [Row | Tail]) ->
|
do_authorize(Client, PubSub, Topic, Columns, [Row | Tail]) ->
|
||||||
case match(Client, PubSub, Topic, format_result(Columns, Row)) of
|
case match(Client, PubSub, Topic, format_result(Columns, Row)) of
|
||||||
{matched, Permission} -> {matched, Permission};
|
{matched, Permission} -> {matched, Permission};
|
||||||
nomatch -> do_check_authz(Client, PubSub, Topic, Columns, Tail)
|
nomatch -> do_authorize(Client, PubSub, Topic, Columns, Tail)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
format_result(Columns, Row) ->
|
format_result(Columns, Row) ->
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
%% ACL Callbacks
|
%% ACL Callbacks
|
||||||
-export([ description/0
|
-export([ description/0
|
||||||
, parse_query/1
|
, parse_query/1
|
||||||
, check_authz/4
|
, authorize/4
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
|
@ -49,25 +49,25 @@ parse_query(Sql) ->
|
||||||
{Sql, []}
|
{Sql, []}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_authz(Client, PubSub, Topic,
|
authorize(Client, PubSub, Topic,
|
||||||
#{<<"resource_id">> := ResourceID,
|
#{<<"resource_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;
|
||||||
{ok, Columns, Rows} ->
|
{ok, Columns, Rows} ->
|
||||||
do_check_authz(Client, PubSub, Topic, Columns, Rows);
|
do_authorize(Client, PubSub, Topic, Columns, Rows);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?LOG(error, "[AuthZ] Query pgsql error: ~p~n", [Reason]),
|
?LOG(error, "[AuthZ] Query pgsql error: ~p~n", [Reason]),
|
||||||
nomatch
|
nomatch
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_check_authz(_Client, _PubSub, _Topic, _Columns, []) ->
|
do_authorize(_Client, _PubSub, _Topic, _Columns, []) ->
|
||||||
nomatch;
|
nomatch;
|
||||||
do_check_authz(Client, PubSub, Topic, Columns, [Row | Tail]) ->
|
do_authorize(Client, PubSub, Topic, Columns, [Row | Tail]) ->
|
||||||
case match(Client, PubSub, Topic, format_result(Columns, Row)) of
|
case match(Client, PubSub, Topic, format_result(Columns, Row)) of
|
||||||
{matched, Permission} -> {matched, Permission};
|
{matched, Permission} -> {matched, Permission};
|
||||||
nomatch -> do_check_authz(Client, PubSub, Topic, Columns, Tail)
|
nomatch -> do_authorize(Client, PubSub, Topic, Columns, Tail)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
format_result(Columns, Row) ->
|
format_result(Columns, Row) ->
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
-include_lib("emqx/include/logger.hrl").
|
-include_lib("emqx/include/logger.hrl").
|
||||||
|
|
||||||
%% ACL Callbacks
|
%% ACL Callbacks
|
||||||
-export([ check_authz/4
|
-export([ authorize/4
|
||||||
, description/0
|
, description/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
description() ->
|
description() ->
|
||||||
"AuthZ with redis".
|
"AuthZ with redis".
|
||||||
|
|
||||||
check_authz(Client, PubSub, Topic,
|
authorize(Client, PubSub, Topic,
|
||||||
#{<<"resource_id">> := ResourceID,
|
#{<<"resource_id">> := ResourceID,
|
||||||
<<"cmd">> := CMD
|
<<"cmd">> := CMD
|
||||||
}) ->
|
}) ->
|
||||||
|
@ -41,22 +41,22 @@ check_authz(Client, PubSub, Topic,
|
||||||
case emqx_resource:query(ResourceID, {cmd, NCMD}) of
|
case emqx_resource:query(ResourceID, {cmd, NCMD}) of
|
||||||
{ok, []} -> nomatch;
|
{ok, []} -> nomatch;
|
||||||
{ok, Rows} ->
|
{ok, Rows} ->
|
||||||
do_check_authz(Client, PubSub, Topic, Rows);
|
do_authorize(Client, PubSub, Topic, Rows);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?LOG(error, "[AuthZ] Query redis error: ~p", [Reason]),
|
?LOG(error, "[AuthZ] Query redis error: ~p", [Reason]),
|
||||||
nomatch
|
nomatch
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_check_authz(_Client, _PubSub, _Topic, []) ->
|
do_authorize(_Client, _PubSub, _Topic, []) ->
|
||||||
nomatch;
|
nomatch;
|
||||||
do_check_authz(Client, PubSub, Topic, [TopicFilter, Action | Tail]) ->
|
do_authorize(Client, PubSub, Topic, [TopicFilter, Action | Tail]) ->
|
||||||
case match(Client, PubSub, Topic,
|
case match(Client, PubSub, Topic,
|
||||||
#{topics => TopicFilter,
|
#{topics => TopicFilter,
|
||||||
action => Action
|
action => Action
|
||||||
})
|
})
|
||||||
of
|
of
|
||||||
{matched, Permission} -> {matched, Permission};
|
{matched, Permission} -> {matched, Permission};
|
||||||
nomatch -> do_check_authz(Client, PubSub, Topic, Tail)
|
nomatch -> do_authorize(Client, PubSub, Topic, Tail)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
match(Client, PubSub, Topic,
|
match(Client, PubSub, Topic,
|
||||||
|
|
|
@ -145,23 +145,23 @@ t_authz(_) ->
|
||||||
Rules4 = [emqx_authz:compile(Rule) || Rule <- [?RULE4, ?RULE1]],
|
Rules4 = [emqx_authz:compile(Rule) || Rule <- [?RULE4, ?RULE1]],
|
||||||
|
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo1, subscribe, <<"#">>, deny, [])),
|
emqx_authz:authorize(ClientInfo1, subscribe, <<"#">>, deny, [])),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo1, subscribe, <<"+">>, deny, Rules1)),
|
emqx_authz:authorize(ClientInfo1, subscribe, <<"+">>, deny, Rules1)),
|
||||||
?assertEqual({stop, allow},
|
?assertEqual({stop, allow},
|
||||||
emqx_authz:check_authz(ClientInfo1, subscribe, <<"+">>, deny, Rules2)),
|
emqx_authz:authorize(ClientInfo1, subscribe, <<"+">>, deny, Rules2)),
|
||||||
?assertEqual({stop, allow},
|
?assertEqual({stop, allow},
|
||||||
emqx_authz:check_authz(ClientInfo1, publish, <<"test">>, deny, Rules3)),
|
emqx_authz:authorize(ClientInfo1, publish, <<"test">>, deny, Rules3)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo1, publish, <<"test">>, deny, Rules4)),
|
emqx_authz:authorize(ClientInfo1, publish, <<"test">>, deny, Rules4)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo2, subscribe, <<"#">>, deny, Rules2)),
|
emqx_authz:authorize(ClientInfo2, subscribe, <<"#">>, deny, Rules2)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo3, publish, <<"test">>, deny, Rules3)),
|
emqx_authz:authorize(ClientInfo3, publish, <<"test">>, deny, Rules3)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo3, publish, <<"fake">>, deny, Rules4)),
|
emqx_authz:authorize(ClientInfo3, publish, <<"fake">>, deny, Rules4)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo4, publish, <<"test">>, deny, Rules3)),
|
emqx_authz:authorize(ClientInfo4, publish, <<"test">>, deny, Rules3)),
|
||||||
?assertEqual({stop, deny},
|
?assertEqual({stop, deny},
|
||||||
emqx_authz:check_authz(ClientInfo4, publish, <<"fake">>, deny, Rules4)),
|
emqx_authz:authorize(ClientInfo4, publish, <<"fake">>, deny, Rules4)),
|
||||||
ok.
|
ok.
|
||||||
|
|
|
@ -95,23 +95,23 @@ t_authz(_) ->
|
||||||
},
|
},
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, []} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, []} end),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"#">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)), % nomatch
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, publish, <<"#">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, publish, <<"#">>)), % nomatch
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE1 ++ ?RULE2} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE1 ++ ?RULE2} end),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"+">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, publish, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, publish, <<"+">>)),
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE2 ++ ?RULE1} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE2 ++ ?RULE1} end),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"#">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"+">>)),
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE3 ++ ?RULE4} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE3 ++ ?RULE4} end),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo2, subscribe, <<"test/test_clientid">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo2, subscribe, <<"test/test_clientid">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo2, publish, <<"test/test_clientid">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo2, publish, <<"test/test_clientid">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo2, subscribe, <<"test/test_username">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo2, subscribe, <<"test/test_username">>)),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo2, publish, <<"test/test_username">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo2, publish, <<"test/test_username">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo3, subscribe, <<"test">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo3, subscribe, <<"test">>)), % nomatch
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo3, publish, <<"test">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo3, publish, <<"test">>)), % nomatch
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
|
@ -95,23 +95,23 @@ t_authz(_) ->
|
||||||
},
|
},
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, []} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, []} end),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"#">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)), % nomatch
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, publish, <<"#">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, publish, <<"#">>)), % nomatch
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE1 ++ ?RULE2} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE1 ++ ?RULE2} end),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"+">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo1, publish, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, publish, <<"+">>)),
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE2 ++ ?RULE1} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE2 ++ ?RULE1} end),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo1, subscribe, <<"#">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo2, subscribe, <<"+">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo2, subscribe, <<"+">>)),
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE3 ++ ?RULE4} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?COLUMNS, ?RULE3 ++ ?RULE4} end),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo2, subscribe, <<"test/test_clientid">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo2, subscribe, <<"test/test_clientid">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo2, publish, <<"test/test_clientid">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo2, publish, <<"test/test_clientid">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo2, subscribe, <<"test/test_username">>)),
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo2, subscribe, <<"test/test_username">>)),
|
||||||
?assertEqual(allow, emqx_access_control:check_authz(ClientInfo2, publish, <<"test/test_username">>)),
|
?assertEqual(allow, emqx_access_control:authorize(ClientInfo2, publish, <<"test/test_username">>)),
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo3, subscribe, <<"test">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo3, subscribe, <<"test">>)), % nomatch
|
||||||
?assertEqual(deny, emqx_access_control:check_authz(ClientInfo3, publish, <<"test">>)), % nomatch
|
?assertEqual(deny, emqx_access_control:authorize(ClientInfo3, publish, <<"test">>)), % nomatch
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
|
@ -84,30 +84,30 @@ t_authz(_) ->
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, []} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, []} end),
|
||||||
% nomatch
|
% nomatch
|
||||||
?assertEqual(deny,
|
?assertEqual(deny,
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, <<"#">>)),
|
emqx_access_control:authorize(ClientInfo, subscribe, <<"#">>)),
|
||||||
?assertEqual(deny,
|
?assertEqual(deny,
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, <<"#">>)),
|
emqx_access_control:authorize(ClientInfo, publish, <<"#">>)),
|
||||||
|
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?RULE1 ++ ?RULE2} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?RULE1 ++ ?RULE2} end),
|
||||||
% nomatch
|
% nomatch
|
||||||
?assertEqual(deny,
|
?assertEqual(deny,
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, <<"+">>)),
|
emqx_access_control:authorize(ClientInfo, subscribe, <<"+">>)),
|
||||||
% nomatch
|
% nomatch
|
||||||
?assertEqual(deny,
|
?assertEqual(deny,
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, <<"test/username">>)),
|
emqx_access_control:authorize(ClientInfo, subscribe, <<"test/username">>)),
|
||||||
|
|
||||||
?assertEqual(allow,
|
?assertEqual(allow,
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, <<"test/clientid">>)),
|
emqx_access_control:authorize(ClientInfo, publish, <<"test/clientid">>)),
|
||||||
?assertEqual(allow,
|
?assertEqual(allow,
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, <<"test/clientid">>)),
|
emqx_access_control:authorize(ClientInfo, publish, <<"test/clientid">>)),
|
||||||
|
|
||||||
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?RULE3} end),
|
meck:expect(emqx_resource, query, fun(_, _) -> {ok, ?RULE3} end),
|
||||||
|
|
||||||
?assertEqual(allow,
|
?assertEqual(allow,
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, <<"#">>)),
|
emqx_access_control:authorize(ClientInfo, subscribe, <<"#">>)),
|
||||||
% nomatch
|
% nomatch
|
||||||
?assertEqual(deny,
|
?assertEqual(deny,
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, <<"#">>)),
|
emqx_access_control:authorize(ClientInfo, publish, <<"#">>)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ code_change(_OldVsn, State, _Extra) ->
|
||||||
|
|
||||||
chann_subscribe(Topic, State = #state{clientid = ClientId}) ->
|
chann_subscribe(Topic, State = #state{clientid = ClientId}) ->
|
||||||
?LOG(debug, "subscribe Topic=~p", [Topic]),
|
?LOG(debug, "subscribe Topic=~p", [Topic]),
|
||||||
case emqx_access_control:check_authz(clientinfo(State), subscribe, Topic) of
|
case emqx_access_control:authorize(clientinfo(State), subscribe, Topic) of
|
||||||
allow ->
|
allow ->
|
||||||
emqx_broker:subscribe(Topic, ClientId, ?SUBOPTS),
|
emqx_broker:subscribe(Topic, ClientId, ?SUBOPTS),
|
||||||
emqx_hooks:run('session.subscribed', [clientinfo(State), Topic, ?SUBOPTS]),
|
emqx_hooks:run('session.subscribed', [clientinfo(State), Topic, ?SUBOPTS]),
|
||||||
|
@ -241,7 +241,7 @@ chann_unsubscribe(Topic, State) ->
|
||||||
|
|
||||||
chann_publish(Topic, Payload, State = #state{clientid = ClientId}) ->
|
chann_publish(Topic, Payload, State = #state{clientid = ClientId}) ->
|
||||||
?LOG(debug, "publish Topic=~p, Payload=~p", [Topic, Payload]),
|
?LOG(debug, "publish Topic=~p, Payload=~p", [Topic, Payload]),
|
||||||
case emqx_access_control:check_authz(clientinfo(State), publish, Topic) of
|
case emqx_access_control:authorize(clientinfo(State), publish, Topic) of
|
||||||
allow ->
|
allow ->
|
||||||
_ = emqx_broker:publish(
|
_ = emqx_broker:publish(
|
||||||
emqx_message:set_flag(retain, false,
|
emqx_message:set_flag(retain, false,
|
||||||
|
|
|
@ -77,7 +77,7 @@ t_publish_acl_deny(_Config) ->
|
||||||
emqx:subscribe(Topic),
|
emqx:subscribe(Topic),
|
||||||
|
|
||||||
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history]),
|
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history]),
|
||||||
ok = meck:expect(emqx_access_control, check_authz, 3, deny),
|
ok = meck:expect(emqx_access_control, authorize, 3, deny),
|
||||||
Reply = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}),
|
Reply = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}),
|
||||||
?assertEqual({error,forbidden}, Reply),
|
?assertEqual({error,forbidden}, Reply),
|
||||||
ok = meck:unload(emqx_access_control),
|
ok = meck:unload(emqx_access_control),
|
||||||
|
@ -114,7 +114,7 @@ t_observe_acl_deny(_Config) ->
|
||||||
Topic = <<"abc">>, TopicStr = binary_to_list(Topic),
|
Topic = <<"abc">>, TopicStr = binary_to_list(Topic),
|
||||||
Uri = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret",
|
Uri = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret",
|
||||||
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history]),
|
ok = meck:new(emqx_access_control, [non_strict, passthrough, no_history]),
|
||||||
ok = meck:expect(emqx_access_control, check_authz, 3, deny),
|
ok = meck:expect(emqx_access_control, authorize, 3, deny),
|
||||||
?assertEqual({error,forbidden}, er_coap_observer:observe(Uri)),
|
?assertEqual({error,forbidden}, er_coap_observer:observe(Uri)),
|
||||||
[] = emqx:subscribers(Topic),
|
[] = emqx:subscribers(Topic),
|
||||||
ok = meck:unload(emqx_access_control).
|
ok = meck:unload(emqx_access_control).
|
||||||
|
@ -289,7 +289,7 @@ t_acl(Config) ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
|
|
||||||
ok = emqx_hooks:del('client.check_authz', {emqx_authz, check_authz}),
|
ok = emqx_hooks:del('client.authorize', {emqx_authz, authorize}),
|
||||||
file:delete(filename:join(emqx:get_env(plugins_etc_dir), 'authz.conf')),
|
file:delete(filename:join(emqx:get_env(plugins_etc_dir), 'authz.conf')),
|
||||||
application:set_env(emqx, plugins_etc_dir, OldPath),
|
application:set_env(emqx, plugins_etc_dir, OldPath),
|
||||||
application:stop(emqx_authz).
|
application:stop(emqx_authz).
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
, {'client.connected', {emqx_exhook_handler, on_client_connected, []}}
|
, {'client.connected', {emqx_exhook_handler, on_client_connected, []}}
|
||||||
, {'client.disconnected', {emqx_exhook_handler, on_client_disconnected, []}}
|
, {'client.disconnected', {emqx_exhook_handler, on_client_disconnected, []}}
|
||||||
, {'client.authenticate', {emqx_exhook_handler, on_client_authenticate, []}}
|
, {'client.authenticate', {emqx_exhook_handler, on_client_authenticate, []}}
|
||||||
, {'client.check_authz', {emqx_exhook_handler, on_client_check_authz, []}}
|
, {'client.authorize', {emqx_exhook_handler, on_client_authorize, []}}
|
||||||
, {'client.subscribe', {emqx_exhook_handler, on_client_subscribe, []}}
|
, {'client.subscribe', {emqx_exhook_handler, on_client_subscribe, []}}
|
||||||
, {'client.unsubscribe', {emqx_exhook_handler, on_client_unsubscribe, []}}
|
, {'client.unsubscribe', {emqx_exhook_handler, on_client_unsubscribe, []}}
|
||||||
, {'session.created', {emqx_exhook_handler, on_session_created, []}}
|
, {'session.created', {emqx_exhook_handler, on_session_created, []}}
|
||||||
|
|
|
@ -40,7 +40,7 @@ service HookProvider {
|
||||||
|
|
||||||
rpc OnClientAuthenticate(ClientAuthenticateRequest) returns (ValuedResponse) {};
|
rpc OnClientAuthenticate(ClientAuthenticateRequest) returns (ValuedResponse) {};
|
||||||
|
|
||||||
rpc OnClientCheckAuthz(ClientCheckAuthzRequest) returns (ValuedResponse) {};
|
rpc OnClientAuthorize(ClientAuthorizeRequest) returns (ValuedResponse) {};
|
||||||
|
|
||||||
rpc OnClientSubscribe(ClientSubscribeRequest) returns (EmptySuccess) {};
|
rpc OnClientSubscribe(ClientSubscribeRequest) returns (EmptySuccess) {};
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ message ClientAuthenticateRequest {
|
||||||
bool result = 2;
|
bool result = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ClientCheckAuthzRequest {
|
message ClientAuthorizeRequest {
|
||||||
|
|
||||||
ClientInfo clientinfo = 1;
|
ClientInfo clientinfo = 1;
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ message ValuedResponse {
|
||||||
|
|
||||||
oneof value {
|
oneof value {
|
||||||
|
|
||||||
// Boolean result, used on the 'client.authenticate', 'client.check_authz' hooks
|
// Boolean result, used on the 'client.authenticate', 'client.authorize' hooks
|
||||||
bool bool_result = 3;
|
bool bool_result = 3;
|
||||||
|
|
||||||
// Message result, used on the 'message.*' hooks
|
// Message result, used on the 'message.*' hooks
|
||||||
|
@ -279,7 +279,7 @@ message HookSpec {
|
||||||
// Available value:
|
// Available value:
|
||||||
// "client.connect", "client.connack"
|
// "client.connect", "client.connack"
|
||||||
// "client.connected", "client.disconnected"
|
// "client.connected", "client.disconnected"
|
||||||
// "client.authenticate", "client.check_authz"
|
// "client.authenticate", "client.authorize"
|
||||||
// "client.subscribe", "client.unsubscribe"
|
// "client.subscribe", "client.unsubscribe"
|
||||||
//
|
//
|
||||||
// "session.created", "session.subscribed"
|
// "session.created", "session.subscribed"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
, on_client_connected/2
|
, on_client_connected/2
|
||||||
, on_client_disconnected/3
|
, on_client_disconnected/3
|
||||||
, on_client_authenticate/2
|
, on_client_authenticate/2
|
||||||
, on_client_check_authz/4
|
, on_client_authorize/4
|
||||||
, on_client_subscribe/3
|
, on_client_subscribe/3
|
||||||
, on_client_unsubscribe/3
|
, on_client_unsubscribe/3
|
||||||
]).
|
]).
|
||||||
|
@ -109,7 +109,7 @@ on_client_authenticate(ClientInfo, AuthResult) ->
|
||||||
{ok, AuthResult}
|
{ok, AuthResult}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
on_client_check_authz(ClientInfo, PubSub, Topic, Result) ->
|
on_client_authorize(ClientInfo, PubSub, Topic, Result) ->
|
||||||
Bool = Result == allow,
|
Bool = Result == allow,
|
||||||
Type = case PubSub of
|
Type = case PubSub of
|
||||||
publish -> 'PUBLISH';
|
publish -> 'PUBLISH';
|
||||||
|
@ -120,7 +120,7 @@ on_client_check_authz(ClientInfo, PubSub, Topic, Result) ->
|
||||||
topic => Topic,
|
topic => Topic,
|
||||||
result => Bool
|
result => Bool
|
||||||
},
|
},
|
||||||
case call_fold('client.check_authz', Req,
|
case call_fold('client.authorize', Req,
|
||||||
fun merge_responsed_bool/2) of
|
fun merge_responsed_bool/2) of
|
||||||
{StopOrOk, #{result := Result0}} when is_boolean(Result0) ->
|
{StopOrOk, #{result := Result0}} when is_boolean(Result0) ->
|
||||||
NResult = case Result0 of true -> allow; _ -> deny end,
|
NResult = case Result0 of true -> allow; _ -> deny end,
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
| 'client.connected'
|
| 'client.connected'
|
||||||
| 'client.disconnected'
|
| 'client.disconnected'
|
||||||
| 'client.authenticate'
|
| 'client.authenticate'
|
||||||
| 'client.check_authz'
|
| 'client.authorize'
|
||||||
| 'client.subscribe'
|
| 'client.subscribe'
|
||||||
| 'client.unsubscribe'
|
| 'client.unsubscribe'
|
||||||
| 'session.created'
|
| 'session.created'
|
||||||
|
@ -297,7 +297,7 @@ hk2func('client.connack') -> 'on_client_connack';
|
||||||
hk2func('client.connected') -> 'on_client_connected';
|
hk2func('client.connected') -> 'on_client_connected';
|
||||||
hk2func('client.disconnected') -> 'on_client_disconnected';
|
hk2func('client.disconnected') -> 'on_client_disconnected';
|
||||||
hk2func('client.authenticate') -> 'on_client_authenticate';
|
hk2func('client.authenticate') -> 'on_client_authenticate';
|
||||||
hk2func('client.check_authz') -> 'on_client_check_authz';
|
hk2func('client.authorize') -> 'on_client_authorize';
|
||||||
hk2func('client.subscribe') -> 'on_client_subscribe';
|
hk2func('client.subscribe') -> 'on_client_subscribe';
|
||||||
hk2func('client.unsubscribe') -> 'on_client_unsubscribe';
|
hk2func('client.unsubscribe') -> 'on_client_unsubscribe';
|
||||||
hk2func('session.created') -> 'on_session_created';
|
hk2func('session.created') -> 'on_session_created';
|
||||||
|
@ -320,7 +320,7 @@ message_hooks() ->
|
||||||
-compile({inline, [available_hooks/0]}).
|
-compile({inline, [available_hooks/0]}).
|
||||||
available_hooks() ->
|
available_hooks() ->
|
||||||
['client.connect', 'client.connack', 'client.connected',
|
['client.connect', 'client.connack', 'client.connected',
|
||||||
'client.disconnected', 'client.authenticate', 'client.check_authz',
|
'client.disconnected', 'client.authenticate', 'client.authorize',
|
||||||
'client.subscribe', 'client.unsubscribe',
|
'client.subscribe', 'client.unsubscribe',
|
||||||
'session.created', 'session.subscribed', 'session.unsubscribed',
|
'session.created', 'session.subscribed', 'session.unsubscribed',
|
||||||
'session.resumed', 'session.discarded', 'session.takeovered',
|
'session.resumed', 'session.discarded', 'session.takeovered',
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
, on_client_connected/2
|
, on_client_connected/2
|
||||||
, on_client_disconnected/2
|
, on_client_disconnected/2
|
||||||
, on_client_authenticate/2
|
, on_client_authenticate/2
|
||||||
, on_client_check_authz/2
|
, on_client_authorize/2
|
||||||
, on_client_subscribe/2
|
, on_client_subscribe/2
|
||||||
, on_client_unsubscribe/2
|
, on_client_unsubscribe/2
|
||||||
, on_session_created/2
|
, on_session_created/2
|
||||||
|
@ -122,7 +122,7 @@ on_provider_loaded(Req, Md) ->
|
||||||
#{name => <<"client.connected">>},
|
#{name => <<"client.connected">>},
|
||||||
#{name => <<"client.disconnected">>},
|
#{name => <<"client.disconnected">>},
|
||||||
#{name => <<"client.authenticate">>},
|
#{name => <<"client.authenticate">>},
|
||||||
#{name => <<"client.check_authz">>},
|
#{name => <<"client.authorize">>},
|
||||||
#{name => <<"client.subscribe">>},
|
#{name => <<"client.subscribe">>},
|
||||||
#{name => <<"client.unsubscribe">>},
|
#{name => <<"client.unsubscribe">>},
|
||||||
#{name => <<"session.created">>},
|
#{name => <<"session.created">>},
|
||||||
|
@ -197,10 +197,10 @@ on_client_authenticate(#{clientinfo := #{username := Username}} = Req, Md) ->
|
||||||
{ok, #{type => 'IGNORE'}, Md}
|
{ok, #{type => 'IGNORE'}, Md}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec on_client_check_authz(emqx_exhook_pb:client_check_authz_request(), grpc:metadata())
|
-spec on_client_authorize(emqx_exhook_pb:client_authorize_request(), grpc:metadata())
|
||||||
-> {ok, emqx_exhook_pb:valued_response(), grpc:metadata()}
|
-> {ok, emqx_exhook_pb:valued_response(), grpc:metadata()}
|
||||||
| {error, grpc_cowboy_h:error_response()}.
|
| {error, grpc_cowboy_h:error_response()}.
|
||||||
on_client_check_authz(#{clientinfo := #{username := Username}} = Req, Md) ->
|
on_client_authorize(#{clientinfo := #{username := Username}} = Req, Md) ->
|
||||||
?MODULE:in({?FUNCTION_NAME, Req}),
|
?MODULE:in({?FUNCTION_NAME, Req}),
|
||||||
%io:format("fun: ~p, req: ~0p~n", [?FUNCTION_NAME, Req]),
|
%io:format("fun: ~p, req: ~0p~n", [?FUNCTION_NAME, Req]),
|
||||||
%% some cases for testing
|
%% some cases for testing
|
||||||
|
|
|
@ -109,14 +109,14 @@ prop_client_authenticate() ->
|
||||||
true
|
true
|
||||||
end).
|
end).
|
||||||
|
|
||||||
prop_client_check_authz() ->
|
prop_client_authorize() ->
|
||||||
?ALL({ClientInfo0, PubSub, Topic, Result},
|
?ALL({ClientInfo0, PubSub, Topic, Result},
|
||||||
{clientinfo(), oneof([publish, subscribe]),
|
{clientinfo(), oneof([publish, subscribe]),
|
||||||
topic(), oneof([allow, deny])},
|
topic(), oneof([allow, deny])},
|
||||||
begin
|
begin
|
||||||
ClientInfo = inject_magic_into(username, ClientInfo0),
|
ClientInfo = inject_magic_into(username, ClientInfo0),
|
||||||
OutResult = emqx_hooks:run_fold(
|
OutResult = emqx_hooks:run_fold(
|
||||||
'client.check_authz',
|
'client.authorize',
|
||||||
[ClientInfo, PubSub, Topic],
|
[ClientInfo, PubSub, Topic],
|
||||||
Result),
|
Result),
|
||||||
ExpectedOutResult = case maps:get(username, ClientInfo) of
|
ExpectedOutResult = case maps:get(username, ClientInfo) of
|
||||||
|
@ -127,7 +127,7 @@ prop_client_check_authz() ->
|
||||||
end,
|
end,
|
||||||
?assertEqual(ExpectedOutResult, OutResult),
|
?assertEqual(ExpectedOutResult, OutResult),
|
||||||
|
|
||||||
{'on_client_check_authz', Resp} = emqx_exhook_demo_svr:take(),
|
{'on_client_authorize', Resp} = emqx_exhook_demo_svr:take(),
|
||||||
Expected =
|
Expected =
|
||||||
#{result => aclresult_to_bool(Result),
|
#{result => aclresult_to_bool(Result),
|
||||||
type => pubsub_to_enum(PubSub),
|
type => pubsub_to_enum(PubSub),
|
||||||
|
|
|
@ -305,7 +305,7 @@ handle_call({subscribe, TopicFilter, Qos},
|
||||||
conn_state = connected,
|
conn_state = connected,
|
||||||
clientinfo = ClientInfo}) ->
|
clientinfo = ClientInfo}) ->
|
||||||
case is_acl_enabled(ClientInfo) andalso
|
case is_acl_enabled(ClientInfo) andalso
|
||||||
emqx_access_control:check_authz(ClientInfo, subscribe, TopicFilter) of
|
emqx_access_control:authorize(ClientInfo, subscribe, TopicFilter) of
|
||||||
deny ->
|
deny ->
|
||||||
{reply, {error, ?RESP_PERMISSION_DENY, <<"ACL deny">>}, Channel};
|
{reply, {error, ?RESP_PERMISSION_DENY, <<"ACL deny">>}, Channel};
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -325,7 +325,7 @@ handle_call({publish, Topic, Qos, Payload},
|
||||||
= #{clientid := From,
|
= #{clientid := From,
|
||||||
mountpoint := Mountpoint}}) ->
|
mountpoint := Mountpoint}}) ->
|
||||||
case is_acl_enabled(ClientInfo) andalso
|
case is_acl_enabled(ClientInfo) andalso
|
||||||
emqx_access_control:check_authz(ClientInfo, publish, Topic) of
|
emqx_access_control:authorize(ClientInfo, publish, Topic) of
|
||||||
deny ->
|
deny ->
|
||||||
{reply, {error, ?RESP_PERMISSION_DENY, <<"ACL deny">>}, Channel};
|
{reply, {error, ?RESP_PERMISSION_DENY, <<"ACL deny">>}, Channel};
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -167,7 +167,7 @@ t_acl_deny(Cfg) ->
|
||||||
Password = <<"123456">>,
|
Password = <<"123456">>,
|
||||||
|
|
||||||
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
|
||||||
ok = meck:expect(emqx_access_control, check_authz, fun(_, _, _) -> deny end),
|
ok = meck:expect(emqx_access_control, authorize, fun(_, _, _) -> deny end),
|
||||||
|
|
||||||
ConnBin = frame_connect(Client, Password),
|
ConnBin = frame_connect(Client, Password),
|
||||||
ConnAckBin = frame_connack(0),
|
ConnAckBin = frame_connack(0),
|
||||||
|
|
|
@ -414,8 +414,8 @@ emqx_collect(emqx_client_authenticate, Stats) ->
|
||||||
counter_metric(?C('client.authenticate', Stats));
|
counter_metric(?C('client.authenticate', Stats));
|
||||||
emqx_collect(emqx_client_auth_anonymous, Stats) ->
|
emqx_collect(emqx_client_auth_anonymous, Stats) ->
|
||||||
counter_metric(?C('client.auth.anonymous', Stats));
|
counter_metric(?C('client.auth.anonymous', Stats));
|
||||||
emqx_collect(emqx_client_check_authz, Stats) ->
|
emqx_collect(emqx_client_authorize, Stats) ->
|
||||||
counter_metric(?C('client.check_authz', Stats));
|
counter_metric(?C('client.authorize', Stats));
|
||||||
emqx_collect(emqx_client_subscribe, Stats) ->
|
emqx_collect(emqx_client_subscribe, Stats) ->
|
||||||
counter_metric(?C('client.subscribe', Stats));
|
counter_metric(?C('client.subscribe', Stats));
|
||||||
emqx_collect(emqx_client_unsubscribe, Stats) ->
|
emqx_collect(emqx_client_unsubscribe, Stats) ->
|
||||||
|
@ -567,7 +567,7 @@ emqx_metrics_client() ->
|
||||||
[ emqx_client_connected
|
[ emqx_client_connected
|
||||||
, emqx_client_authenticate
|
, emqx_client_authenticate
|
||||||
, emqx_client_auth_anonymous
|
, emqx_client_auth_anonymous
|
||||||
, emqx_client_check_authz
|
, emqx_client_authorize
|
||||||
, emqx_client_subscribe
|
, emqx_client_subscribe
|
||||||
, emqx_client_unsubscribe
|
, emqx_client_unsubscribe
|
||||||
, emqx_client_disconnected
|
, emqx_client_disconnected
|
||||||
|
|
Loading…
Reference in New Issue