Replace credentials with client
This commit is contained in:
parent
32b2a01d68
commit
d99c9daf76
|
@ -28,52 +28,57 @@
|
|||
%% APIs
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec(authenticate(emqx_types:credentials())
|
||||
-> {ok, emqx_types:credentials()} | {error, term()}).
|
||||
authenticate(Credentials) ->
|
||||
case emqx_hooks:run_fold('client.authenticate', [], init_auth_result(Credentials)) of
|
||||
#{auth_result := success, anonymous := true} = NewCredentials ->
|
||||
-spec(authenticate(emqx_types:client())
|
||||
-> {ok, #{auth_result := emqx_types:auth_result(),
|
||||
anonymous := boolean}} | {error, term()}).
|
||||
authenticate(Client = #{zone := Zone}) ->
|
||||
case emqx_hooks:run_fold('client.authenticate',
|
||||
[Client], default_auth_result(Zone)) of
|
||||
Result = #{auth_result := success, anonymous := true} ->
|
||||
emqx_metrics:inc('auth.mqtt.anonymous'),
|
||||
{ok, NewCredentials};
|
||||
#{auth_result := success} = NewCredentials ->
|
||||
{ok, NewCredentials};
|
||||
NewCredentials ->
|
||||
{error, maps:get(auth_result, NewCredentials, unknown_error)}
|
||||
end.
|
||||
|
||||
%% @doc Check ACL
|
||||
-spec(check_acl(emqx_types:credentials(), emqx_types:pubsub(), emqx_types:topic())
|
||||
-> allow | deny).
|
||||
check_acl(Credentials, PubSub, Topic) ->
|
||||
case emqx_acl_cache:is_enabled() of
|
||||
false ->
|
||||
do_check_acl(Credentials, PubSub, Topic);
|
||||
true ->
|
||||
case emqx_acl_cache:get_acl_cache(PubSub, Topic) of
|
||||
not_found ->
|
||||
AclResult = do_check_acl(Credentials, PubSub, Topic),
|
||||
emqx_acl_cache:put_acl_cache(PubSub, Topic, AclResult),
|
||||
AclResult;
|
||||
AclResult -> AclResult
|
||||
end
|
||||
{ok, Result};
|
||||
Result = #{auth_result := success} ->
|
||||
{ok, Result};
|
||||
Result ->
|
||||
{error, maps:get(auth_result, Result, unknown_error)}
|
||||
end.
|
||||
|
||||
do_check_acl(#{zone := Zone} = Credentials, PubSub, Topic) ->
|
||||
case emqx_hooks:run_fold('client.check_acl', [Credentials, PubSub, Topic],
|
||||
emqx_zone:get_env(Zone, acl_nomatch, deny)) of
|
||||
allow -> allow;
|
||||
_ -> deny
|
||||
%% @doc Check ACL
|
||||
-spec(check_acl(emqx_types:cient(), emqx_types:pubsub(), emqx_types:topic())
|
||||
-> allow | deny).
|
||||
check_acl(Client, PubSub, Topic) ->
|
||||
case emqx_acl_cache:is_enabled() of
|
||||
true ->
|
||||
check_acl_cache(Client, PubSub, Topic);
|
||||
false ->
|
||||
do_check_acl(Client, PubSub, Topic)
|
||||
end.
|
||||
|
||||
check_acl_cache(Client, PubSub, Topic) ->
|
||||
case emqx_acl_cache:get_acl_cache(PubSub, Topic) of
|
||||
not_found ->
|
||||
AclResult = do_check_acl(Client, PubSub, Topic),
|
||||
emqx_acl_cache:put_acl_cache(PubSub, Topic, AclResult),
|
||||
AclResult;
|
||||
AclResult -> AclResult
|
||||
end.
|
||||
|
||||
do_check_acl(#{zone := Zone} = Client, PubSub, Topic) ->
|
||||
Default = emqx_zone:get_env(Zone, acl_nomatch, deny),
|
||||
case emqx_hooks:run_fold('client.check_acl', [Client, PubSub, Topic], Default) of
|
||||
allow -> allow;
|
||||
_Other -> deny
|
||||
end.
|
||||
|
||||
-spec(reload_acl() -> ok | {error, term()}).
|
||||
reload_acl() ->
|
||||
emqx_acl_cache:is_enabled() andalso
|
||||
emqx_acl_cache:empty_acl_cache(),
|
||||
emqx_acl_cache:is_enabled()
|
||||
andalso emqx_acl_cache:empty_acl_cache(),
|
||||
emqx_mod_acl_internal:reload_acl().
|
||||
|
||||
init_auth_result(Credentials) ->
|
||||
case emqx_zone:get_env(maps:get(zone, Credentials, undefined), allow_anonymous, false) of
|
||||
true -> Credentials#{auth_result => success, anonymous => true};
|
||||
false -> Credentials#{auth_result => not_authorized, anonymous => false}
|
||||
default_auth_result(Zone) ->
|
||||
case emqx_zone:get_env(Zone, allow_anonymous, false) of
|
||||
true -> #{auth_result => success, anonymous => true};
|
||||
false -> #{auth_result => not_authorized, anonymous => false}
|
||||
end.
|
||||
|
||||
|
|
|
@ -40,10 +40,6 @@
|
|||
-define(ALLOW_DENY(A), ((A =:= allow) orelse (A =:= deny))).
|
||||
-define(PUBSUB(A), ((A =:= subscribe) orelse (A =:= publish) orelse (A =:= pubsub))).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% APIs
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc Compile Access Rule.
|
||||
compile({A, all}) when ?ALLOW_DENY(A) ->
|
||||
{A, all};
|
||||
|
@ -92,21 +88,21 @@ bin(B) when is_binary(B) ->
|
|||
%% @doc Match access rule
|
||||
-spec(match(emqx_types:credentials(), emqx_types:topic(), rule())
|
||||
-> {matched, allow} | {matched, deny} | nomatch).
|
||||
match(_Credentials, _Topic, {AllowDeny, all}) when ?ALLOW_DENY(AllowDeny) ->
|
||||
match(_Client, _Topic, {AllowDeny, all}) when ?ALLOW_DENY(AllowDeny) ->
|
||||
{matched, AllowDeny};
|
||||
match(Credentials, Topic, {AllowDeny, Who, _PubSub, TopicFilters})
|
||||
match(Client, Topic, {AllowDeny, Who, _PubSub, TopicFilters})
|
||||
when ?ALLOW_DENY(AllowDeny) ->
|
||||
case match_who(Credentials, Who)
|
||||
andalso match_topics(Credentials, Topic, TopicFilters) of
|
||||
case match_who(Client, Who)
|
||||
andalso match_topics(Client, Topic, TopicFilters) of
|
||||
true -> {matched, AllowDeny};
|
||||
false -> nomatch
|
||||
end.
|
||||
|
||||
match_who(_Credentials, all) ->
|
||||
match_who(_Client, all) ->
|
||||
true;
|
||||
match_who(_Credentials, {user, all}) ->
|
||||
match_who(_Client, {user, all}) ->
|
||||
true;
|
||||
match_who(_Credentials, {client, all}) ->
|
||||
match_who(_Client, {client, all}) ->
|
||||
true;
|
||||
match_who(#{client_id := ClientId}, {client, ClientId}) ->
|
||||
true;
|
||||
|
@ -116,44 +112,44 @@ match_who(#{peername := undefined}, {ipaddr, _Tup}) ->
|
|||
false;
|
||||
match_who(#{peername := {IP, _}}, {ipaddr, CIDR}) ->
|
||||
esockd_cidr:match(IP, CIDR);
|
||||
match_who(Credentials, {'and', Conds}) when is_list(Conds) ->
|
||||
match_who(Client, {'and', Conds}) when is_list(Conds) ->
|
||||
lists:foldl(fun(Who, Allow) ->
|
||||
match_who(Credentials, Who) andalso Allow
|
||||
match_who(Client, Who) andalso Allow
|
||||
end, true, Conds);
|
||||
match_who(Credentials, {'or', Conds}) when is_list(Conds) ->
|
||||
match_who(Client, {'or', Conds}) when is_list(Conds) ->
|
||||
lists:foldl(fun(Who, Allow) ->
|
||||
match_who(Credentials, Who) orelse Allow
|
||||
match_who(Client, Who) orelse Allow
|
||||
end, false, Conds);
|
||||
match_who(_Credentials, _Who) ->
|
||||
match_who(_Client, _Who) ->
|
||||
false.
|
||||
|
||||
match_topics(_Credentials, _Topic, []) ->
|
||||
match_topics(_Client, _Topic, []) ->
|
||||
false;
|
||||
match_topics(Credentials, Topic, [{pattern, PatternFilter}|Filters]) ->
|
||||
TopicFilter = feed_var(Credentials, PatternFilter),
|
||||
match_topics(Client, Topic, [{pattern, PatternFilter}|Filters]) ->
|
||||
TopicFilter = feed_var(Client, PatternFilter),
|
||||
match_topic(emqx_topic:words(Topic), TopicFilter)
|
||||
orelse match_topics(Credentials, Topic, Filters);
|
||||
match_topics(Credentials, Topic, [TopicFilter|Filters]) ->
|
||||
orelse match_topics(Client, Topic, Filters);
|
||||
match_topics(Client, Topic, [TopicFilter|Filters]) ->
|
||||
match_topic(emqx_topic:words(Topic), TopicFilter)
|
||||
orelse match_topics(Credentials, Topic, Filters).
|
||||
orelse match_topics(Client, Topic, Filters).
|
||||
|
||||
match_topic(Topic, {eq, TopicFilter}) ->
|
||||
Topic == TopicFilter;
|
||||
match_topic(Topic, TopicFilter) ->
|
||||
emqx_topic:match(Topic, TopicFilter).
|
||||
|
||||
feed_var(Credentials, Pattern) ->
|
||||
feed_var(Credentials, Pattern, []).
|
||||
feed_var(_Credentials, [], Acc) ->
|
||||
feed_var(Client, Pattern) ->
|
||||
feed_var(Client, Pattern, []).
|
||||
feed_var(_Client, [], Acc) ->
|
||||
lists:reverse(Acc);
|
||||
feed_var(Credentials = #{client_id := undefined}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(Credentials, Words, [<<"%c">>|Acc]);
|
||||
feed_var(Credentials = #{client_id := ClientId}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(Credentials, Words, [ClientId |Acc]);
|
||||
feed_var(Credentials = #{username := undefined}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(Credentials, Words, [<<"%u">>|Acc]);
|
||||
feed_var(Credentials = #{username := Username}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(Credentials, Words, [Username|Acc]);
|
||||
feed_var(Credentials, [W|Words], Acc) ->
|
||||
feed_var(Credentials, Words, [W|Acc]).
|
||||
feed_var(Client = #{client_id := undefined}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(Client, Words, [<<"%c">>|Acc]);
|
||||
feed_var(Client = #{client_id := ClientId}, [<<"%c">>|Words], Acc) ->
|
||||
feed_var(Client, Words, [ClientId |Acc]);
|
||||
feed_var(Client = #{username := undefined}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(Client, Words, [<<"%u">>|Acc]);
|
||||
feed_var(Client = #{username := Username}, [<<"%u">>|Words], Acc) ->
|
||||
feed_var(Client, Words, [Username|Acc]);
|
||||
feed_var(Client, [W|Words], Acc) ->
|
||||
feed_var(Client, Words, [W|Acc]).
|
||||
|
||||
|
|
Loading…
Reference in New Issue