Merge pull request #8002 from JimMoen/refactor-auth-metrics

refactor(metrics): clearer auth success/failure metrics
This commit is contained in:
JianBo He 2022-05-23 09:02:58 +08:00 committed by GitHub
commit 25e67bf3f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 239 additions and 351 deletions

View File

@ -23,6 +23,7 @@ File format:
* Add proto_name and proto_ver fields for $event/client_disconnected event. * Add proto_name and proto_ver fields for $event/client_disconnected event.
* Mnesia auth/acl http api support multiple condition queries. * Mnesia auth/acl http api support multiple condition queries.
* Inflight QoS1 Messages for shared topics are now redispatched to another alive subscribers upon chosen subscriber session termination. * Inflight QoS1 Messages for shared topics are now redispatched to another alive subscribers upon chosen subscriber session termination.
* Make auth metrics name more understandable.
### Bug fixes ### Bug fixes
* List subscription topic (/api/v4/subscriptions), the result do not match with multiple conditions. * List subscription topic (/api/v4/subscriptions), the result do not match with multiple conditions.

View File

@ -1,14 +1 @@
-define(APP, emqx_auth_http). -define(APP, emqx_auth_http).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,6 +1,6 @@
{application, emqx_auth_http, {application, emqx_auth_http,
[{description, "EMQ X Authentication/ACL with HTTP API"}, [{description, "EMQ X Authentication/ACL with HTTP API"},
{vsn, "4.3.5"}, % strict semver, bump manually! {vsn, "4.3.6"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_http_sup]}, {registered, [emqx_auth_http_sup]},
{applications, [kernel,stdlib,ehttpc]}, {applications, [kernel,stdlib,ehttpc]},

View File

@ -1,27 +1,38 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
{VSN, {VSN,
[{"4.3.4", [{"4.3.5",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]} [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
]}, {load_module,emqx_auth_http,brutal_purge,soft_purge,[]}]},
{"4.3.4",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]}]},
{"4.3.3", {"4.3.3",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]},
{"4.3.2", {"4.3.2",
[{apply,{application,stop,[emqx_auth_http]}}, [{apply,{application,stop,[emqx_auth_http]}},
{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_http,brutal_purge,soft_purge,[]}, {load_module,emqx_acl_http,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]},
{<<"4.3.[0-1]">>, {<<"4.3.[0-1]">>,
[{restart_application,emqx_auth_http}]}, [{restart_application,emqx_auth_http}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.4", [{"4.3.5",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}]}, [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]}]},
{"4.3.4",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]}]},
{"4.3.3", {"4.3.3",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]},
{"4.3.2", {"4.3.2",
[{apply,{application,stop,[emqx_auth_http]}}, [{apply,{application,stop,[emqx_auth_http]}},
{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_http,brutal_purge,soft_purge,[]}, {load_module,emqx_acl_http,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]},
{<<"4.3.[0-1]">>, {<<"4.3.[0-1]">>,

View File

@ -30,22 +30,16 @@
]). ]).
%% Callbacks %% Callbacks
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
]). ]).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
check(ClientInfo, AuthResult, #{auth := AuthParms = #{path := Path}, check(ClientInfo, AuthResult, #{auth := AuthParms = #{path := Path},
super := SuperParams}) -> super := SuperParams}) ->
case authenticate(AuthParms, ClientInfo) of case authenticate(AuthParms, ClientInfo) of
{ok, 200, <<"ignore">>} -> {ok, 200, <<"ignore">>} ->
emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; ok;
{ok, 200, Body} -> {ok, 200, Body} ->
emqx_metrics:inc(?AUTH_METRICS(success)),
IsSuperuser = is_superuser(SuperParams, ClientInfo), IsSuperuser = is_superuser(SuperParams, ClientInfo),
{stop, AuthResult#{is_superuser => IsSuperuser, {stop, AuthResult#{is_superuser => IsSuperuser,
auth_result => success, auth_result => success,
@ -54,12 +48,10 @@ check(ClientInfo, AuthResult, #{auth := AuthParms = #{path := Path},
{ok, Code, _Body} -> {ok, Code, _Body} ->
?LOG(error, "Deny connection from path: ~s, response http code: ~p", ?LOG(error, "Deny connection from path: ~s, response http code: ~p",
[Path, Code]), [Path, Code]),
emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => http_to_connack_error(Code), {stop, AuthResult#{auth_result => http_to_connack_error(Code),
anonymous => false}}; anonymous => false}};
{error, Error} -> {error, Error} ->
?LOG(error, "Request auth path: ~s, error: ~p", [Path, Error]), ?LOG(error, "Request auth path: ~s, error: ~p", [Path, Error]),
emqx_metrics:inc(?AUTH_METRICS(failure)),
%%FIXME later: server_unavailable is not right. %%FIXME later: server_unavailable is not right.
{stop, AuthResult#{auth_result => server_unavailable, {stop, AuthResult#{auth_result => server_unavailable,
anonymous => false}} anonymous => false}}

View File

@ -112,7 +112,6 @@ load_hooks() ->
case application:get_env(?APP, auth_req) of case application:get_env(?APP, auth_req) of
undefined -> ok; undefined -> ok;
{ok, AuthReq} -> {ok, AuthReq} ->
ok = emqx_auth_http:register_metrics(),
PoolOpts = proplists:get_value(pool_opts, AuthReq), PoolOpts = proplists:get_value(pool_opts, AuthReq),
PoolName = proplists:get_value(pool_name, AuthReq), PoolName = proplists:get_value(pool_name, AuthReq),
{ok, _} = ehttpc_sup:start_pool(PoolName, PoolOpts), {ok, _} = ehttpc_sup:start_pool(PoolName, PoolOpts),
@ -160,4 +159,3 @@ path(#{path := ""}) ->
"/"; "/";
path(#{path := Path}) -> path(#{path := Path}) ->
Path. Path.

View File

@ -1,13 +1,9 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.2", [{<<"4\\.3\\.[0-2]">>,
[{restart_application,emqx_auth_jwt}]},
{<<"4\\.3\\.[0-1]">>,
[{restart_application,emqx_auth_jwt}]}, [{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.2", [{<<"4\\.3\\.[0-2]">>,
[{restart_application,emqx_auth_jwt}]},
{<<"4\\.3\\.[0-1]">>,
[{restart_application,emqx_auth_jwt}]}, [{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -21,28 +21,11 @@
-logger_header("[JWT]"). -logger_header("[JWT]").
-export([ register_metrics/0 -export([ check_auth/3
, check_auth/3
, check_acl/5 , check_acl/5
, description/0 , description/0
]). ]).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Authentication callbacks %% Authentication callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -50,17 +33,16 @@ register_metrics() ->
check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) -> check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) ->
case maps:find(From, ClientInfo) of case maps:find(From, ClientInfo) of
error -> error ->
ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{ok, undefined} -> {ok, undefined} ->
ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{ok, Token} -> {ok, Token} ->
case emqx_auth_jwt_svr:verify(Token) of case emqx_auth_jwt_svr:verify(Token) of
{error, not_found} -> {error, not_found} ->
ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{error, not_token} -> {error, not_token} ->
ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{error, Reason} -> {error, Reason} ->
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => Reason, anonymous => false}}; {stop, AuthResult#{auth_result => Reason, anonymous => false}};
{ok, Claims} -> {ok, Claims} ->
{stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))} {stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))}
@ -121,10 +103,8 @@ verify_acl(ClientInfo, [AclTopic | AclTopics], Topic) ->
verify_claims(Checklists, Claims, ClientInfo) -> verify_claims(Checklists, Claims, ClientInfo) ->
case do_verify_claims(feedvar(Checklists, ClientInfo), Claims) of case do_verify_claims(feedvar(Checklists, ClientInfo), Claims) of
{error, Reason} -> {error, Reason} ->
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
#{auth_result => Reason, anonymous => false}; #{auth_result => Reason, anonymous => false};
ok -> ok ->
ok = emqx_metrics:inc(?AUTH_METRICS(success)),
#{auth_result => success, anonymous => false, jwt_claims => Claims} #{auth_result => success, anonymous => false, jwt_claims => Claims}
end. end.

View File

@ -32,7 +32,6 @@ start(_Type, _Args) ->
{ok, Sup} = supervisor:start_link({local, ?MODULE}, ?MODULE, []), {ok, Sup} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
{ok, _} = start_auth_server(jwks_svr_options()), {ok, _} = start_auth_server(jwks_svr_options()),
ok = emqx_auth_jwt:register_metrics(),
AuthEnv = auth_env(), AuthEnv = auth_env(),
_ = emqx:hook('client.authenticate', {emqx_auth_jwt, check_auth, [AuthEnv]}), _ = emqx:hook('client.authenticate', {emqx_auth_jwt, check_auth, [AuthEnv]}),

View File

@ -1,14 +1 @@
-define(APP, emqx_auth_ldap). -define(APP, emqx_auth_ldap).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,6 +1,6 @@
{application, emqx_auth_ldap, {application, emqx_auth_ldap,
[{description, "EMQ X Authentication/ACL with LDAP"}, [{description, "EMQ X Authentication/ACL with LDAP"},
{vsn, "4.3.4"}, % strict semver, bump manually! {vsn, "4.3.5"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_ldap_sup]}, {registered, [emqx_auth_ldap_sup]},
{applications, [kernel,stdlib,eldap2,ecpool]}, {applications, [kernel,stdlib,eldap2,ecpool]},

View File

@ -1,40 +1,29 @@
%% -*-: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[ {"4.3.3", [ [{<<"4\\.3\\.[3-4]">>,
%% There are only changes to the schema file, so we don't need [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
%% any commands here. {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}]},
]},
{"4.3.0",
[ {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []}
, {load_module, emqx_auth_ldap_cli, brutal_purge, soft_purge, []}
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []}
]},
{"4.3.1",
[ {load_module, emqx_auth_ldap_cli, brutal_purge, soft_purge, []}
, {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []}
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []}
]},
{"4.3.2", {"4.3.2",
[ {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []} [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []} {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
]}, {load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]}]},
{<<".*">>, []} {<<"4\\.3\\.[0-1]">>,
], [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
[ {"4.3.3", []}, {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{"4.3.0", {load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
[ {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []} {load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},
, {load_module, emqx_auth_ldap_cli, brutal_purge, soft_purge, []} {<<".*">>,[]}],
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []} [{<<"4\\.3\\.[3-4]">>,
]}, [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
{"4.3.1", {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}]},
[ {load_module, emqx_auth_ldap_cli, brutal_purge, soft_purge, []}
, {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []}
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []}
]},
{"4.3.2", {"4.3.2",
[ {load_module, emqx_acl_ldap, brutal_purge, soft_purge, []} [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
, {load_module, emqx_auth_ldap_app, brutal_purge, soft_purge, []} {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
]}, {load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]}]},
{<<".*">>, []} {<<"4\\.3\\.[0-1]">>,
] [{load_module,emqx_auth_ldap_app,brutal_purge,soft_purge,[]},
}. {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.

View File

@ -26,17 +26,12 @@
-import(emqx_auth_ldap_cli, [search/3]). -import(emqx_auth_ldap_cli, [search/3]).
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
, prepare_filter/4 , prepare_filter/4
, replace_vars/2 , replace_vars/2
]). ]).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
check(ClientInfo = #{username := Username, password := Password}, AuthResult, check(ClientInfo = #{username := Username, password := Password}, AuthResult,
State = #{password_attr := PasswdAttr, bind_as_user := BindAsUserRequired, pool := Pool}) -> State = #{password_attr := PasswdAttr, bind_as_user := BindAsUserRequired, pool := Pool}) ->
CheckResult = CheckResult =
@ -63,12 +58,10 @@ check(ClientInfo = #{username := Username, password := Password}, AuthResult,
end, end,
case CheckResult of case CheckResult of
ok -> ok ->
ok = emqx_metrics:inc(?AUTH_METRICS(success)),
{stop, AuthResult#{auth_result => success, anonymous => false}}; {stop, AuthResult#{auth_result => success, anonymous => false}};
{error, not_found} -> {error, not_found} ->
emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{error, ResultCode} -> {error, ResultCode} ->
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
?LOG(error, "[LDAP] Auth from ldap failed: ~p", [ResultCode]), ?LOG(error, "[LDAP] Auth from ldap failed: ~p", [ResultCode]),
{stop, AuthResult#{auth_result => ResultCode, anonymous => false}} {stop, AuthResult#{auth_result => ResultCode, anonymous => false}}
end. end.

View File

@ -49,7 +49,6 @@ stop(_State) ->
ok. ok.
load_auth_hook(DeviceDn) -> load_auth_hook(DeviceDn) ->
ok = emqx_auth_ldap:register_metrics(),
Params = maps:from_list(DeviceDn), Params = maps:from_list(DeviceDn),
emqx:hook('client.authenticate', fun emqx_auth_ldap:check/3, [Params#{pool => ?APP}]). emqx:hook('client.authenticate', fun emqx_auth_ldap:check/3, [Params#{pool => ?APP}]).

View File

@ -41,15 +41,3 @@
}). }).
-type(acl_record() :: {acl_target(), emqx_topic:topic(), action(), access(), created_at()}). -type(acl_record() :: {acl_target(), emqx_topic:topic(), action(), access(), created_at()}).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -2,7 +2,9 @@
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{<<"4\\.3\\.[5-6]">>, [{<<"4\\.3\\.[5-6]">>,
[{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-3]">>, {<<"4\\.3\\.[0-3]">>,
@ -27,7 +29,9 @@
{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{<<"4\\.3\\.[5-6]">>, [{<<"4\\.3\\.[5-6]">>,
[{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-3]">>, {<<"4\\.3\\.[0-3]">>,

View File

@ -27,7 +27,6 @@
-define(TABLE, emqx_user). -define(TABLE, emqx_user).
%% Auth callbacks %% Auth callbacks
-export([ init/1 -export([ init/1
, register_metrics/0
, check/3 , check/3
, description/0 , description/0
]). ]).
@ -51,10 +50,6 @@ init(#{clientid_list := ClientidList, username_list := UsernameList}) ->
ok = ekka_mnesia:copy_table(?TABLE, disc_copies). ok = ekka_mnesia:copy_table(?TABLE, disc_copies).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
hash_type() -> hash_type() ->
application:get_env(emqx_auth_mnesia, password_hash, sha256). application:get_env(emqx_auth_mnesia, password_hash, sha256).
@ -67,17 +62,14 @@ check(ClientInfo = #{ clientid := Clientid
end), end),
case ets:select(?TABLE, MatchSpec) of case ets:select(?TABLE, MatchSpec) of
[] -> [] ->
emqx_metrics:inc(?AUTH_METRICS(ignore)),
ok; ok;
List -> List ->
case match_password(NPassword, HashType, List) of case match_password(NPassword, HashType, List) of
false -> false ->
Info = maps:without([password], ClientInfo), Info = maps:without([password], ClientInfo),
?LOG(info, "[Mnesia] Auth from mnesia failed: ~p", [Info]), ?LOG(info, "[Mnesia] Auth from mnesia failed: ~p", [Info]),
emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{anonymous => false, auth_result => password_error}}; {stop, AuthResult#{anonymous => false, auth_result => password_error}};
_ -> _ ->
emqx_metrics:inc(?AUTH_METRICS(success)),
{stop, AuthResult#{anonymous => false, auth_result => success}} {stop, AuthResult#{anonymous => false, auth_result => success}}
end end
end. end.

View File

@ -56,7 +56,6 @@ load_auth_hook() ->
ClientidList = application:get_env(?APP, clientid_list, []), ClientidList = application:get_env(?APP, clientid_list, []),
UsernameList = application:get_env(?APP, username_list, []), UsernameList = application:get_env(?APP, username_list, []),
ok = emqx_auth_mnesia:init(#{clientid_list => ClientidList, username_list => UsernameList}), ok = emqx_auth_mnesia:init(#{clientid_list => ClientidList, username_list => UsernameList}),
ok = emqx_auth_mnesia:register_metrics(),
Params = #{hash_type => emqx_auth_mnesia:hash_type()}, Params = #{hash_type => emqx_auth_mnesia:hash_type()},
emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]). emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]).

View File

@ -1,4 +1,3 @@
-define(APP, emqx_auth_mongo). -define(APP, emqx_auth_mongo).
-define(DEFAULT_SELECTORS, [{<<"username">>, <<"%u">>}]). -define(DEFAULT_SELECTORS, [{<<"username">>, <<"%u">>}]).
@ -14,15 +13,3 @@
-record(aclquery, {collection = <<"mqtt_acl">>, -record(aclquery, {collection = <<"mqtt_acl">>,
selector = {<<"username">>, <<"%u">>}}). selector = {<<"username">>, <<"%u">>}}).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,6 +1,6 @@
{application, emqx_auth_mongo, {application, emqx_auth_mongo,
[{description, "EMQ X Authentication/ACL with MongoDB"}, [{description, "EMQ X Authentication/ACL with MongoDB"},
{vsn, "4.3.3"}, % strict semver, bump manually! {vsn, "4.3.4"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_mongo_sup]}, {registered, [emqx_auth_mongo_sup]},
{applications, [kernel,stdlib,mongodb,ecpool]}, {applications, [kernel,stdlib,mongodb,ecpool]},

View File

@ -1,10 +1,7 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.2", [{<<"4\\.3\\.[1-3]">>,
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.3.1",
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
@ -12,10 +9,7 @@
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.2", [{<<"4\\.3\\.[1-3]">>,
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.3.1",
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",

View File

@ -23,8 +23,7 @@
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/types.hrl"). -include_lib("emqx/include/types.hrl").
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
]). ]).
@ -39,20 +38,15 @@
, available/3 , available/3
]). ]).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
check(ClientInfo = #{password := Password}, AuthResult, check(ClientInfo = #{password := Password}, AuthResult,
Env = #{authquery := AuthQuery, superquery := SuperQuery}) -> Env = #{authquery := AuthQuery, superquery := SuperQuery}) ->
#authquery{collection = Collection, field = Fields, #authquery{collection = Collection, field = Fields,
hash = HashType, selector = Selector} = AuthQuery, hash = HashType, selector = Selector} = AuthQuery,
Pool = maps:get(pool, Env, ?APP), Pool = maps:get(pool, Env, ?APP),
case query(Pool, Collection, maps:from_list(replvars(Selector, ClientInfo))) of case query(Pool, Collection, maps:from_list(replvars(Selector, ClientInfo))) of
undefined -> emqx_metrics:inc(?AUTH_METRICS(ignore)); undefined -> ok;
{error, Reason} -> {error, Reason} ->
?LOG(error, "[MongoDB] Can't connect to MongoDB server: ~0p", [Reason]), ?LOG(error, "[MongoDB] Can't connect to MongoDB server: ~0p", [Reason]),
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => not_authorized, anonymous => false}}; {stop, AuthResult#{auth_result => not_authorized, anonymous => false}};
UserMap -> UserMap ->
Result = case [maps:get(Field, UserMap, undefined) || Field <- Fields] of Result = case [maps:get(Field, UserMap, undefined) || Field <- Fields] of
@ -64,13 +58,11 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case Result of case Result of
ok -> ok ->
ok = emqx_metrics:inc(?AUTH_METRICS(success)),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};
{error, Error} -> {error, Error} ->
?LOG(error, "[MongoDB] check auth fail: ~p", [Error]), ?LOG(error, "[MongoDB] check auth fail: ~p", [Error]),
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => Error, anonymous => false}} {stop, AuthResult#{auth_result => Error, anonymous => false}}
end end
end. end.

View File

@ -68,7 +68,6 @@ safe_start() ->
reg_authmod(AuthQuery) -> reg_authmod(AuthQuery) ->
case emqx_auth_mongo:available(?APP, AuthQuery) of case emqx_auth_mongo:available(?APP, AuthQuery) of
ok -> ok ->
emqx_auth_mongo:register_metrics(),
HookFun = fun emqx_auth_mongo:check/3, HookFun = fun emqx_auth_mongo:check/3,
HookOptions = #{authquery => AuthQuery, superquery => undefined, pool => ?APP}, HookOptions = #{authquery => AuthQuery, superquery => undefined, pool => ?APP},
case r(super_query, application:get_env(?APP, super_query, undefined)) of case r(super_query, application:get_env(?APP, super_query, undefined)) of
@ -122,4 +121,3 @@ r(auth_query, Config) ->
r(acl_query, Config) -> r(acl_query, Config) ->
#aclquery{collection = list_to_binary(get_value(collection, Config, "mqtt_acl")), #aclquery{collection = list_to_binary(get_value(collection, Config, "mqtt_acl")),
selector = get_value(selector, Config, [?DEFAULT_SELECTORS])}. selector = get_value(selector, Config, [?DEFAULT_SELECTORS])}.

View File

@ -1,14 +1 @@
-define(APP, emqx_auth_mysql). -define(APP, emqx_auth_mysql).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,6 +1,6 @@
{application, emqx_auth_mysql, {application, emqx_auth_mysql,
[{description, "EMQ X Authentication/ACL with MySQL"}, [{description, "EMQ X Authentication/ACL with MySQL"},
{vsn, "4.3.2"}, % strict semver, bump manually! {vsn, "4.3.3"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_mysql_sup]}, {registered, [emqx_auth_mysql_sup]},
{applications, [kernel,stdlib,mysql,ecpool]}, {applications, [kernel,stdlib,mysql,ecpool]},

View File

@ -1,16 +1,19 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
{VSN, {VSN,
[{"4.3.1", [ [{<<"4\\.3\\.[1-2]">>,
%% There are only changes to the schema file, so we don't need [{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
%% any commands here. {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
]},
{"4.3.0", {"4.3.0",
[{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.1", []}, [{<<"4\\.3\\.[1-2]">>,
[{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
[{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}] {<<".*">>,[]}]
}. }.

View File

@ -22,17 +22,12 @@
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/types.hrl"). -include_lib("emqx/include/types.hrl").
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
]). ]).
-define(EMPTY(Username), (Username =:= undefined orelse Username =:= <<>>)). -define(EMPTY(Username), (Username =:= undefined orelse Username =:= <<>>)).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
check(ClientInfo = #{password := Password}, AuthResult, check(ClientInfo = #{password := Password}, AuthResult,
#{auth_query := {AuthSql, AuthParams}, #{auth_query := {AuthSql, AuthParams},
super_query := SuperQuery, super_query := SuperQuery,
@ -51,15 +46,13 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case CheckPass of case CheckPass of
ok -> ok ->
emqx_metrics:inc(?AUTH_METRICS(success)),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};
{error, not_found} -> {error, not_found} ->
emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; ok;
{error, ResultCode} -> {error, ResultCode} ->
?LOG(error, "[MySQL] Auth from mysql failed: ~p", [ResultCode]), ?LOG(error, "[MySQL] Auth from mysql failed: ~p", [ResultCode]),
emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => ResultCode, anonymous => false}} {stop, AuthResult#{auth_result => ResultCode, anonymous => false}}
end. end.
@ -88,4 +81,3 @@ check_pass(Password, HashType) ->
end. end.
description() -> "Authentication with MySQL". description() -> "Authentication with MySQL".

View File

@ -50,7 +50,6 @@ stop(_State) ->
ok. ok.
load_auth_hook(AuthQuery) -> load_auth_hook(AuthQuery) ->
ok = emqx_auth_mysql:register_metrics(),
SuperQuery = parse_query(application:get_env(?APP, super_query, undefined)), SuperQuery = parse_query(application:get_env(?APP, super_query, undefined)),
{ok, HashType} = application:get_env(?APP, password_hash), {ok, HashType} = application:get_env(?APP, password_hash),
Params = #{auth_query => AuthQuery, Params = #{auth_query => AuthQuery,

View File

@ -1,13 +1 @@
-define(APP, emqx_auth_pgsql). -define(APP, emqx_auth_pgsql).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,31 +1,25 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[ [{<<"4\\.3\\.[1-2]">>,
{"4.3.2", [
%% epgsql 4.4.0 -> 4.6.0. %% epgsql 4.4.0 -> 4.6.0.
%% epgsql has no appup ,so we can only restart it. %% epgsql has no appup ,so we can only restart it.
{restart_application, epgsql} [{restart_application,epgsql},
]},
{"4.3.1", [
{restart_application, epgsql}
]},
{"4.3.0", [
{restart_application, epgsql},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]} {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
]}, {"4.3.0",
[{restart_application,epgsql},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[ [{<<"4\\.3\\.[1-2]">>,
{"4.3.2", [ [{restart_application,epgsql},
{restart_application, epgsql}
]},
{"4.3.1", [
{restart_application, epgsql}
]},
{"4.3.0", [
{restart_application, epgsql},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]} {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
]}, {"4.3.0",
{<<".*">>,[]}] [{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
}. {restart_application,epgsql},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.

View File

@ -21,15 +21,10 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
]). ]).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Auth Module Callbacks %% Auth Module Callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -50,15 +45,13 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case CheckPass of case CheckPass of
ok -> ok ->
emqx_metrics:inc(?AUTH_METRICS(success)),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};
{error, not_found} -> {error, not_found} ->
emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; ok;
{error, ResultCode} -> {error, ResultCode} ->
?LOG(error, "[Postgres] Auth from pgsql failed: ~p", [ResultCode]), ?LOG(error, "[Postgres] Auth from pgsql failed: ~p", [ResultCode]),
emqx_metrics:inc(?AUTH_METRICS(failure)),
{stop, AuthResult#{auth_result => ResultCode, anonymous => false}} {stop, AuthResult#{auth_result => ResultCode, anonymous => false}}
end. end.
@ -88,4 +81,3 @@ check_pass(Password, HashType) ->
end. end.
description() -> "Authentication with PostgreSQL". description() -> "Authentication with PostgreSQL".

View File

@ -42,7 +42,6 @@ start(_StartType, _StartArgs) ->
super_query => SuperQuery, super_query => SuperQuery,
hash_type => HashType, hash_type => HashType,
pool => ?APP}, pool => ?APP},
ok = emqx_auth_pgsql:register_metrics(),
ok = emqx:hook('client.authenticate', fun emqx_auth_pgsql:check/3, [AuthEnv]) ok = emqx:hook('client.authenticate', fun emqx_auth_pgsql:check/3, [AuthEnv])
end), end),
if_enabled(acl_query, fun(AclQuery) -> if_enabled(acl_query, fun(AclQuery) ->
@ -59,4 +58,3 @@ if_enabled(Par, Fun) ->
{ok, Query} -> Fun(parse_query(Par, Query)); {ok, Query} -> Fun(parse_query(Par, Query));
undefined -> ok undefined -> ok
end. end.

View File

@ -1,14 +1 @@
-define(APP, emqx_auth_redis). -define(APP, emqx_auth_redis).
-record(auth_metrics, {
success = 'client.auth.success',
failure = 'client.auth.failure',
ignore = 'client.auth.ignore'
}).
-define(METRICS(Type), tl(tuple_to_list(#Type{}))).
-define(METRICS(Type, K), #Type{}#Type.K).
-define(AUTH_METRICS, ?METRICS(auth_metrics)).
-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)).

View File

@ -1,6 +1,6 @@
{application, emqx_auth_redis, {application, emqx_auth_redis,
[{description, "EMQ X Authentication/ACL with Redis"}, [{description, "EMQ X Authentication/ACL with Redis"},
{vsn, "4.3.2"}, % strict semver, bump manually! {vsn, "4.3.3"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_redis_sup]}, {registered, [emqx_auth_redis_sup]},
{applications, [kernel,stdlib,eredis,eredis_cluster,ecpool]}, {applications, [kernel,stdlib,eredis,eredis_cluster,ecpool]},

View File

@ -1,16 +1,19 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
{VSN, {VSN,
[{"4.3.1", [ [{<<"4\\.3\\.[1-2]">>,
%% There are only changes to the schema file, so we don't need [{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
%% any commands here. {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
]},
{"4.3.0", {"4.3.0",
[{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.1", []}, [{<<"4\\.3\\.[1-2]">>,
[{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
[{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}] {<<".*">>,[]}]
}. }.

View File

@ -21,15 +21,10 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-export([ register_metrics/0 -export([ check/3
, check/3
, description/0 , description/0
]). ]).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
check(ClientInfo = #{password := Password}, AuthResult, check(ClientInfo = #{password := Password}, AuthResult,
#{auth_cmd := AuthCmd, #{auth_cmd := AuthCmd,
super_cmd := SuperCmd, super_cmd := SuperCmd,
@ -52,15 +47,13 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case CheckPass of case CheckPass of
ok -> ok ->
ok = emqx_metrics:inc(?AUTH_METRICS(success)),
IsSuperuser = is_superuser(Pool, Type, SuperCmd, ClientInfo, Timeout), IsSuperuser = is_superuser(Pool, Type, SuperCmd, ClientInfo, Timeout),
{stop, AuthResult#{is_superuser => IsSuperuser, {stop, AuthResult#{is_superuser => IsSuperuser,
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};
{error, not_found} -> {error, not_found} ->
ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); ok;
{error, ResultCode} -> {error, ResultCode} ->
ok = emqx_metrics:inc(?AUTH_METRICS(failure)),
?LOG(error, "[Redis] Auth from redis failed: ~p", [ResultCode]), ?LOG(error, "[Redis] Auth from redis failed: ~p", [ResultCode]),
{stop, AuthResult#{auth_result => ResultCode, anonymous => false}} {stop, AuthResult#{auth_result => ResultCode, anonymous => false}}
end. end.
@ -82,4 +75,3 @@ check_pass(Password, HashType) ->
ok -> ok; ok -> ok;
{error, _Reason} -> {error, not_authorized} {error, _Reason} -> {error, not_authorized}
end. end.

View File

@ -49,7 +49,6 @@ load_auth_hook(AuthCmd) ->
timeout => Timeout, timeout => Timeout,
type => Type, type => Type,
pool => ?APP}, pool => ?APP},
ok = emqx_auth_redis:register_metrics(),
emqx:hook('client.authenticate', fun emqx_auth_redis:check/3, [Config]). emqx:hook('client.authenticate', fun emqx_auth_redis:check/3, [Config]).
load_acl_hook(AclCmd) -> load_acl_hook(AclCmd) ->
@ -66,4 +65,3 @@ if_cmd_enabled(Par, Fun) ->
{ok, Cmd} -> Fun(Cmd); {ok, Cmd} -> Fun(Cmd);
undefined -> ok undefined -> ok
end. end.

View File

@ -1,6 +1,6 @@
{application, emqx_exproto, {application, emqx_exproto,
[{description, "EMQ X Extension for Protocol"}, [{description, "EMQ X Extension for Protocol"},
{vsn, "4.3.7"}, %% 4.3.3 is used by ee {vsn, "4.3.8"}, %% 4.3.3 is used by ee
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{mod, {emqx_exproto_app, []}}, {mod, {emqx_exproto_app, []}},

View File

@ -1,14 +1,9 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[ [{<<"4\\.3\\.[6-7]">>,
{"4.3.6", [{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
[ %% There are only changes to the schema file, so we don't need any {<<"4\\.3\\.[2-5]">>,
%% commands here
]},
{<<"4\\.3\\.[4-5]">>,
[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]},
{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[2-3]">>,
[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]},
{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-1]">>, {<<"4\\.3\\.[0-1]">>,
@ -17,11 +12,9 @@
{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, {load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]},
{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.6", []}, [{<<"4\\.3\\.[6-7]">>,
{<<"4\\.3\\.[4-5]">>, [{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, {<<"4\\.3\\.[2-5]">>,
{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[2-3]">>,
[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]},
{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-1]">>, {<<"4\\.3\\.[0-1]">>,

View File

@ -299,8 +299,6 @@ handle_call({auth, RequestedClientInfo, Password},
case emqx_access_control:authenticate(ClientInfo1#{password => Password}) of case emqx_access_control:authenticate(ClientInfo1#{password => Password}) of
{ok, AuthResult} -> {ok, AuthResult} ->
emqx_logger:set_metadata_clientid(ClientId), emqx_logger:set_metadata_clientid(ClientId),
is_anonymous(AuthResult) andalso
emqx_metrics:inc('client.auth.anonymous'),
NClientInfo = maps:merge(ClientInfo1, AuthResult), NClientInfo = maps:merge(ClientInfo1, AuthResult),
NChannel = Channel1#channel{clientinfo = NClientInfo}, NChannel = Channel1#channel{clientinfo = NClientInfo},
case emqx_cm:open_session(true, NClientInfo, NConnInfo) of case emqx_cm:open_session(true, NClientInfo, NConnInfo) of
@ -424,9 +422,6 @@ terminate(Reason, Channel) ->
Req = #{reason => stringfy(Reason)}, Req = #{reason => stringfy(Reason)},
try_dispatch(on_socket_closed, wrap(Req), Channel). try_dispatch(on_socket_closed, wrap(Req), Channel).
is_anonymous(#{anonymous := true}) -> true;
is_anonymous(_AuthResult) -> false.
packet_to_message(Topic, Qos, Payload, packet_to_message(Topic, Qos, Payload,
#channel{ #channel{
conninfo = #{proto_ver := ProtoVer}, conninfo = #{proto_ver := ProtoVer},

View File

@ -1,6 +1,6 @@
{application, emqx_prometheus, {application, emqx_prometheus,
[{description, "Prometheus for EMQ X"}, [{description, "Prometheus for EMQ X"},
{vsn, "4.3.0"}, % strict semver, bump manually! {vsn, "4.3.1"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_prometheus_sup]}, {registered, [emqx_prometheus_sup]},
{applications, [kernel,stdlib,prometheus]}, {applications, [kernel,stdlib,prometheus]},

View File

@ -0,0 +1,9 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
[{"4.3.0",
[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
[{"4.3.0",
[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.

View File

@ -412,8 +412,8 @@ emqx_collect(emqx_client_connected, Stats) ->
counter_metric(?C('client.connected', Stats)); counter_metric(?C('client.connected', Stats));
emqx_collect(emqx_client_authenticate, Stats) -> 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_success_anonymous, Stats) ->
counter_metric(?C('client.auth.anonymous', Stats)); counter_metric(?C('client.auth.success.anonymous', Stats));
emqx_collect(emqx_client_check_acl, Stats) -> emqx_collect(emqx_client_check_acl, Stats) ->
counter_metric(?C('client.check_acl', Stats)); counter_metric(?C('client.check_acl', Stats));
emqx_collect(emqx_client_subscribe, Stats) -> emqx_collect(emqx_client_subscribe, Stats) ->
@ -566,7 +566,7 @@ emqx_metrics_delivery() ->
emqx_metrics_client() -> emqx_metrics_client() ->
[ emqx_client_connected [ emqx_client_connected
, emqx_client_authenticate , emqx_client_authenticate
, emqx_client_auth_anonymous , emqx_client_auth_success_anonymous
, emqx_client_check_acl , emqx_client_check_acl
, emqx_client_subscribe , emqx_client_subscribe
, emqx_client_unsubscribe , emqx_client_unsubscribe

View File

@ -8,6 +8,9 @@
{load_module,emqx_frame,brutal_purge,soft_purge,[]}, {load_module,emqx_frame,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, {load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.3.14", {"4.3.14",
[{load_module,emqx_misc,brutal_purge,soft_purge,[]}, [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
@ -20,6 +23,9 @@
{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]},
{load_module,emqx_frame,brutal_purge,soft_purge,[]}, {load_module,emqx_frame,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_hooks,brutal_purge,soft_purge,[]}]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}]},
{"4.3.13", {"4.3.13",
[{load_module,emqx_session,brutal_purge,soft_purge,[]}, [{load_module,emqx_session,brutal_purge,soft_purge,[]},
@ -37,6 +43,9 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_cm,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]}, {load_module,emqx_misc,brutal_purge,soft_purge,[]},
{load_module,emqx_connection,brutal_purge,soft_purge,[]}]}, {load_module,emqx_connection,brutal_purge,soft_purge,[]}]},
@ -56,6 +65,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
@ -79,6 +89,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_connection,brutal_purge,soft_purge,[]}, {load_module,emqx_connection,brutal_purge,soft_purge,[]},
@ -107,6 +118,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
@ -134,6 +146,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -166,6 +179,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -197,6 +211,7 @@
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -229,6 +244,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -261,6 +277,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -293,6 +310,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -326,6 +344,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -360,6 +379,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -393,6 +413,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_vm,brutal_purge,soft_purge,[]}, {load_module,emqx_vm,brutal_purge,soft_purge,[]},
@ -430,6 +451,7 @@
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_vm_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]}, {load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{apply,{emqx_metrics,assign_auth_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}}, {apply,{emqx_metrics,assign_acl_stats_from_ets_to_counter,[]}},
{apply,{emqx_metrics,upgrade_retained_delayed_counter_type,[]}}, {apply,{emqx_metrics,upgrade_retained_delayed_counter_type,[]}},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]}, {load_module,emqx_access_control,brutal_purge,soft_purge,[]},
@ -469,8 +491,10 @@
{load_module,emqx_session,brutal_purge,soft_purge,[]}, {load_module,emqx_session,brutal_purge,soft_purge,[]},
{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{load_module,emqx_frame,brutal_purge,soft_purge,[]}, {load_module,emqx_frame,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, {load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.3.14", {"4.3.14",
[{load_module,emqx_misc,brutal_purge,soft_purge,[]}, [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
@ -478,6 +502,8 @@
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, {load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
{load_module,emqx,brutal_purge,soft_purge,[]}, {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]},
{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]},
@ -498,6 +524,8 @@
{load_module,emqx_banned,brutal_purge,soft_purge,[]}, {load_module,emqx_banned,brutal_purge,soft_purge,[]},
{load_module,emqx_os_mon,brutal_purge,soft_purge,[]}, {load_module,emqx_os_mon,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
{load_module,emqx_metrics,brutal_purge,soft_purge,[]},
{load_module,emqx_access_control,brutal_purge,soft_purge,[]},
{load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_ctl,brutal_purge,soft_purge,[]}, {load_module,emqx_ctl,brutal_purge,soft_purge,[]},

View File

@ -34,11 +34,15 @@
-spec(authenticate(emqx_types:clientinfo()) -> {ok, result()} | {error, term()}). -spec(authenticate(emqx_types:clientinfo()) -> {ok, result()} | {error, term()}).
authenticate(ClientInfo = #{zone := Zone}) -> authenticate(ClientInfo = #{zone := Zone}) ->
AuthResult = default_auth_result(Zone), AuthResult = default_auth_result(Zone),
case emqx_zone:get_env(Zone, bypass_auth_plugins, false) of case
begin ok = emqx_metrics:inc('client.authenticate'),
emqx_zone:get_env(Zone, bypass_auth_plugins, false)
end
of
true -> true ->
return_auth_result(AuthResult); return_auth_result(AuthResult);
false -> false ->
return_auth_result(run_hooks('client.authenticate', [ClientInfo], AuthResult)) return_auth_result(emqx_hooks:run_fold('client.authenticate', [ClientInfo], AuthResult))
end. end.
%% @doc Check ACL %% @doc Check ACL
@ -51,6 +55,10 @@ check_acl(ClientInfo, PubSub, Topic) ->
end, end,
inc_acl_metrics(Result), Result. inc_acl_metrics(Result), Result.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
%% ACL
check_acl_cache(ClientInfo, PubSub, Topic) -> check_acl_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 ->
@ -64,21 +72,16 @@ check_acl_cache(ClientInfo, PubSub, Topic) ->
do_check_acl(ClientInfo = #{zone := Zone}, PubSub, Topic) -> do_check_acl(ClientInfo = #{zone := Zone}, PubSub, Topic) ->
Default = emqx_zone:get_env(Zone, acl_nomatch, deny), Default = emqx_zone:get_env(Zone, acl_nomatch, deny),
case run_hooks('client.check_acl', [ClientInfo, PubSub, Topic], Default) of case
begin
ok = emqx_metrics:inc('client.check_acl'),
emqx_hooks:run_fold('client.check_acl', [ClientInfo, PubSub, Topic], Default)
end
of
allow -> allow; allow -> allow;
_Other -> deny _Other -> deny
end. end.
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.
-compile({inline, [run_hooks/3]}).
run_hooks(Name, Args, Acc) ->
ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc).
-compile({inline, [inc_acl_metrics/1]}). -compile({inline, [inc_acl_metrics/1]}).
inc_acl_metrics(allow) -> inc_acl_metrics(allow) ->
emqx_metrics:inc('client.acl.allow'); emqx_metrics:inc('client.acl.allow');
@ -87,8 +90,26 @@ inc_acl_metrics(deny) ->
inc_acl_metrics(cache_hit) -> inc_acl_metrics(cache_hit) ->
emqx_metrics:inc('client.acl.cache_hit'). emqx_metrics:inc('client.acl.cache_hit').
%% Auth
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.
-compile({inline, [return_auth_result/1]}). -compile({inline, [return_auth_result/1]}).
return_auth_result(Result = #{auth_result := success}) -> return_auth_result(AuthResult = #{auth_result := success}) ->
{ok, Result}; inc_auth_success_metrics(AuthResult),
return_auth_result(Result) -> {ok, AuthResult};
{error, maps:get(auth_result, Result, unknown_error)}. return_auth_result(AuthResult) ->
emqx_metrics:inc('client.auth.failure'),
{error, maps:get(auth_result, AuthResult, unknown_error)}.
-compile({inline, [inc_auth_success_metrics/1]}).
inc_auth_success_metrics(AuthResult) ->
is_anonymous(AuthResult) andalso
emqx_metrics:inc('client.auth.success.anonymous'),
emqx_metrics:inc('client.auth.success').
is_anonymous(#{anonymous := true}) -> true;
is_anonymous(_AuthResult) -> false.

View File

@ -1285,8 +1285,6 @@ auth_connect(#mqtt_packet_connect{password = Password},
username := Username} = ClientInfo, username := Username} = ClientInfo,
case emqx_access_control:authenticate(ClientInfo#{password => Password}) of case emqx_access_control:authenticate(ClientInfo#{password => Password}) of
{ok, AuthResult} -> {ok, AuthResult} ->
is_anonymous(AuthResult) andalso
emqx_metrics:inc('client.auth.anonymous'),
NClientInfo = maps:merge(ClientInfo, AuthResult), NClientInfo = maps:merge(ClientInfo, AuthResult),
{ok, Channel#channel{clientinfo = NClientInfo}}; {ok, Channel#channel{clientinfo = NClientInfo}};
{error, Reason} -> {error, Reason} ->
@ -1295,9 +1293,6 @@ auth_connect(#mqtt_packet_connect{password = Password},
{error, emqx_reason_codes:connack_error(Reason)} {error, emqx_reason_codes:connack_error(Reason)}
end. end.
is_anonymous(#{anonymous := true}) -> true;
is_anonymous(_AuthResult) -> false.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Enhanced Authentication %% Enhanced Authentication

View File

@ -68,8 +68,10 @@
%% BACKW %% BACKW
-export([%% v4.3.0 -export([%% v4.3.0
upgrade_retained_delayed_counter_type/0, upgrade_retained_delayed_counter_type/0,
%% e4.4.0, e4.3.0-e4.3.6, v4.3.0-v4.3.11 %% v4.3.0-v4.3.11, e4.3.0-e4.3.6; v4.4.0, e4.4.0
assign_acl_stats_from_ets_to_counter/0 assign_acl_stats_from_ets_to_counter/0,
%% v4.3.0-v4.3.14, e4.3.0-e4.3.9; v4.4.0-v4.4.3, e4.4.0-e4.4.3,
assign_auth_stats_from_ets_to_counter/0
]). ]).
-export_type([metric_idx/0]). -export_type([metric_idx/0]).
@ -174,7 +176,6 @@
{counter, 'client.connack'}, {counter, 'client.connack'},
{counter, 'client.connected'}, {counter, 'client.connected'},
{counter, 'client.authenticate'}, {counter, 'client.authenticate'},
{counter, 'client.auth.anonymous'},
{counter, 'client.check_acl'}, {counter, 'client.check_acl'},
{counter, 'client.subscribe'}, {counter, 'client.subscribe'},
{counter, 'client.unsubscribe'}, {counter, 'client.unsubscribe'},
@ -189,8 +190,16 @@
{counter, 'session.discarded'}, {counter, 'session.discarded'},
{counter, 'session.terminated'} {counter, 'session.terminated'}
]). ]).
%% Statistic metrics for ACL checking
-define(STASTS_ACL_METRICS, %% Statistic metrics for auth checking
-define(STATS_AUTH_METRICS,
[ {counter, 'client.auth.success'},
{counter, 'client.auth.success.anonymous'},
{counter, 'client.auth.failure'}
]).
%% Statistic metrics for ACL checking stats
-define(STATS_ACL_METRICS,
[ {counter, 'client.acl.allow'}, [ {counter, 'client.acl.allow'},
{counter, 'client.acl.deny'}, {counter, 'client.acl.deny'},
{counter, 'client.acl.cache_hit'} {counter, 'client.acl.cache_hit'}
@ -228,6 +237,21 @@ assign_acl_stats_from_ets_to_counter() ->
ok = counters:put(CRef, Idx, Val) ok = counters:put(CRef, Idx, Val)
end, Names). end, Names).
%% BACKW: %% v4.3.0-v4.3.14, e4.3.0-e4.3.9; v4.4.0-v4.4.3, e4.4.0-e4.4.3,
assign_auth_stats_from_ets_to_counter() ->
CRef = persistent_term:get(?MODULE),
Names = ['client.auth.success', 'client.auth.success.anonymous', 'client.auth.failure'],
lists:foreach(fun(Name) ->
Val = case emqx_metrics:val(Name) of
undefined -> 0;
Val0 -> Val0
end,
Idx = reserved_idx(Name),
Metric = #metric{name = Name, type = counter, idx = Idx},
ok = gen_server:call(?SERVER, {set, Metric}),
ok = counters:put(CRef, Idx, Val)
end, Names).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Metrics API %% Metrics API
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -458,7 +482,8 @@ init([]) ->
?DELIVERY_METRICS, ?DELIVERY_METRICS,
?CLIENT_METRICS, ?CLIENT_METRICS,
?SESSION_METRICS, ?SESSION_METRICS,
?STASTS_ACL_METRICS ?STATS_AUTH_METRICS,
?STATS_ACL_METRICS
]), ]),
% Store reserved indices % Store reserved indices
ok = lists:foreach(fun({Type, Name}) -> ok = lists:foreach(fun({Type, Name}) ->
@ -592,7 +617,6 @@ reserved_idx('client.connack') -> 201;
reserved_idx('client.connected') -> 202; 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.check_acl') -> 206; reserved_idx('client.check_acl') -> 206;
reserved_idx('client.subscribe') -> 207; reserved_idx('client.subscribe') -> 207;
reserved_idx('client.unsubscribe') -> 208; reserved_idx('client.unsubscribe') -> 208;
@ -604,9 +628,13 @@ reserved_idx('session.takeovered') -> 222;
reserved_idx('session.discarded') -> 223; reserved_idx('session.discarded') -> 223;
reserved_idx('session.terminated') -> 224; reserved_idx('session.terminated') -> 224;
%% Stats metrics %% Stats metrics
%% ACL
reserved_idx('client.acl.allow') -> 300; reserved_idx('client.acl.allow') -> 300;
reserved_idx('client.acl.deny') -> 301; reserved_idx('client.acl.deny') -> 301;
reserved_idx('client.acl.cache_hit') -> 302; reserved_idx('client.acl.cache_hit') -> 302;
%% Auth
reserved_idx('client.auth.success') -> 310;
reserved_idx('client.auth.success.anonymous') -> 311;
reserved_idx('client.auth.failure') -> 312;
reserved_idx(_) -> undefined. reserved_idx(_) -> undefined.