Merge pull request #8226 from savonarola/listener-anonymous
feat(authn): add enable_authn flag for listeners
This commit is contained in:
commit
584a1a6415
|
@ -2063,6 +2063,23 @@ Type of the rate limit.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base_listener_enable_authn {
|
||||||
|
desc {
|
||||||
|
en: """
|
||||||
|
Set <code>true</code> (default) to enable client authentication on this listener.
|
||||||
|
When set to <code>false</code> clients will be allowed to connect without authentication.
|
||||||
|
"""
|
||||||
|
zh: """
|
||||||
|
配置 <code>true</code> (默认值)启用客户端进行身份认证。
|
||||||
|
配置 <code>false</code> 时,将不对客户端做任何认证。
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
label: {
|
||||||
|
en: "Enable authentication"
|
||||||
|
zh: "启用身份认证"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mqtt_listener_access_rules {
|
mqtt_listener_access_rules {
|
||||||
desc {
|
desc {
|
||||||
en: """
|
en: """
|
||||||
|
|
|
@ -214,6 +214,8 @@ when
|
||||||
%% Authenticate
|
%% Authenticate
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
authenticate(#{enable_authn := false}, _AuthResult) ->
|
||||||
|
ignore;
|
||||||
authenticate(#{listener := Listener, protocol := Protocol} = Credential, _AuthResult) ->
|
authenticate(#{listener := Listener, protocol := Protocol} = Credential, _AuthResult) ->
|
||||||
case get_authenticators(Listener, global_chain(Protocol)) of
|
case get_authenticators(Listener, global_chain(Protocol)) of
|
||||||
{ok, ChainName, Authenticators} ->
|
{ok, ChainName, Authenticators} ->
|
||||||
|
|
|
@ -102,7 +102,11 @@
|
||||||
|
|
||||||
-type channel() :: #channel{}.
|
-type channel() :: #channel{}.
|
||||||
|
|
||||||
-type opts() :: #{zone := atom(), listener := {Type :: atom(), Name :: atom()}, atom() => term()}.
|
-type opts() :: #{
|
||||||
|
zone := atom(),
|
||||||
|
listener := {Type :: atom(), Name :: atom()},
|
||||||
|
atom() => term()
|
||||||
|
}.
|
||||||
|
|
||||||
-type conn_state() :: idle | connecting | connected | reauthenticating | disconnected.
|
-type conn_state() :: idle | connecting | connected | reauthenticating | disconnected.
|
||||||
|
|
||||||
|
@ -235,7 +239,11 @@ init(
|
||||||
peername := {PeerHost, _Port},
|
peername := {PeerHost, _Port},
|
||||||
sockname := {_Host, SockPort}
|
sockname := {_Host, SockPort}
|
||||||
},
|
},
|
||||||
#{zone := Zone, limiter := LimiterCfg, listener := {Type, Listener}}
|
#{
|
||||||
|
zone := Zone,
|
||||||
|
limiter := LimiterCfg,
|
||||||
|
listener := {Type, Listener}
|
||||||
|
} = Opts
|
||||||
) ->
|
) ->
|
||||||
Peercert = maps:get(peercert, ConnInfo, undefined),
|
Peercert = maps:get(peercert, ConnInfo, undefined),
|
||||||
Protocol = maps:get(protocol, ConnInfo, mqtt),
|
Protocol = maps:get(protocol, ConnInfo, mqtt),
|
||||||
|
@ -256,7 +264,8 @@ init(
|
||||||
username => undefined,
|
username => undefined,
|
||||||
mountpoint => MountPoint,
|
mountpoint => MountPoint,
|
||||||
is_bridge => false,
|
is_bridge => false,
|
||||||
is_superuser => false
|
is_superuser => false,
|
||||||
|
enable_authn => maps:get(enable_authn, Opts, true)
|
||||||
},
|
},
|
||||||
Zone
|
Zone
|
||||||
),
|
),
|
||||||
|
|
|
@ -304,7 +304,8 @@ do_start_listener(Type, ListenerName, #{bind := ListenOn} = Opts) when
|
||||||
#{
|
#{
|
||||||
listener => {Type, ListenerName},
|
listener => {Type, ListenerName},
|
||||||
zone => zone(Opts),
|
zone => zone(Opts),
|
||||||
limiter => limiter(Opts)
|
limiter => limiter(Opts),
|
||||||
|
enable_authn => enable_authn(Opts)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
);
|
);
|
||||||
|
@ -430,7 +431,8 @@ ws_opts(Type, ListenerName, Opts) ->
|
||||||
{emqx_map_lib:deep_get([websocket, mqtt_path], Opts, "/mqtt"), emqx_ws_connection, #{
|
{emqx_map_lib:deep_get([websocket, mqtt_path], Opts, "/mqtt"), emqx_ws_connection, #{
|
||||||
zone => zone(Opts),
|
zone => zone(Opts),
|
||||||
listener => {Type, ListenerName},
|
listener => {Type, ListenerName},
|
||||||
limiter => limiter(Opts)
|
limiter => limiter(Opts),
|
||||||
|
enable_authn => enable_authn(Opts)
|
||||||
}}
|
}}
|
||||||
],
|
],
|
||||||
Dispatch = cowboy_router:compile([{'_', WsPaths}]),
|
Dispatch = cowboy_router:compile([{'_', WsPaths}]),
|
||||||
|
@ -515,6 +517,9 @@ zone(Opts) ->
|
||||||
limiter(Opts) ->
|
limiter(Opts) ->
|
||||||
maps:get(limiter, Opts, #{}).
|
maps:get(limiter, Opts, #{}).
|
||||||
|
|
||||||
|
enable_authn(Opts) ->
|
||||||
|
maps:get(enable_authn, Opts, true).
|
||||||
|
|
||||||
ssl_opts(Opts) ->
|
ssl_opts(Opts) ->
|
||||||
maps:to_list(
|
maps:to_list(
|
||||||
emqx_tls_lib:drop_tls13_for_old_otp(
|
emqx_tls_lib:drop_tls13_for_old_otp(
|
||||||
|
|
|
@ -1616,6 +1616,14 @@ base_listener(Bind) ->
|
||||||
desc => ?DESC(base_listener_limiter),
|
desc => ?DESC(base_listener_limiter),
|
||||||
default => #{<<"connection">> => <<"default">>}
|
default => #{<<"connection">> => <<"default">>}
|
||||||
}
|
}
|
||||||
|
)},
|
||||||
|
{"enable_authn",
|
||||||
|
sc(
|
||||||
|
boolean(),
|
||||||
|
#{
|
||||||
|
desc => ?DESC(base_listener_enable_authn),
|
||||||
|
default => true
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
change_emqx_opts/1,
|
|
||||||
change_emqx_opts/2,
|
|
||||||
client_ssl/0,
|
client_ssl/0,
|
||||||
client_ssl/1,
|
client_ssl/1,
|
||||||
client_ssl_twoway/0,
|
client_ssl_twoway/0,
|
||||||
|
@ -320,58 +318,6 @@ wait_for(Fn, Ln, F, Timeout) ->
|
||||||
{Pid, Mref} = erlang:spawn_monitor(fun() -> wait_loop(F, catch_call(F)) end),
|
{Pid, Mref} = erlang:spawn_monitor(fun() -> wait_loop(F, catch_call(F)) end),
|
||||||
wait_for_down(Fn, Ln, Timeout, Pid, Mref, false).
|
wait_for_down(Fn, Ln, Timeout, Pid, Mref, false).
|
||||||
|
|
||||||
change_emqx_opts(SslType) ->
|
|
||||||
change_emqx_opts(SslType, []).
|
|
||||||
|
|
||||||
change_emqx_opts(SslType, MoreOpts) ->
|
|
||||||
{ok, Listeners} = application:get_env(emqx, listeners),
|
|
||||||
NewListeners =
|
|
||||||
lists:map(
|
|
||||||
fun(Listener) ->
|
|
||||||
maybe_inject_listener_ssl_options(SslType, MoreOpts, Listener)
|
|
||||||
end,
|
|
||||||
Listeners
|
|
||||||
),
|
|
||||||
emqx_conf:update([listeners], NewListeners, #{}).
|
|
||||||
|
|
||||||
maybe_inject_listener_ssl_options(SslType, MoreOpts, {sll, Port, Opts}) ->
|
|
||||||
%% this clause is kept to be backward compatible
|
|
||||||
%% new config for listener is a map, old is a three-element tuple
|
|
||||||
{ssl, Port, inject_listener_ssl_options(SslType, Opts, MoreOpts)};
|
|
||||||
maybe_inject_listener_ssl_options(SslType, MoreOpts, #{proto := ssl, opts := Opts} = Listener) ->
|
|
||||||
Listener#{opts := inject_listener_ssl_options(SslType, Opts, MoreOpts)};
|
|
||||||
maybe_inject_listener_ssl_options(_SslType, _MoreOpts, Listener) ->
|
|
||||||
Listener.
|
|
||||||
|
|
||||||
inject_listener_ssl_options(SslType, Opts, MoreOpts) ->
|
|
||||||
SslOpts = proplists:get_value(ssl_options, Opts),
|
|
||||||
Keyfile = app_path(emqx, filename:join(["etc", "certs", "key.pem"])),
|
|
||||||
Certfile = app_path(emqx, filename:join(["etc", "certs", "cert.pem"])),
|
|
||||||
TupleList1 = lists:keyreplace(keyfile, 1, SslOpts, {keyfile, Keyfile}),
|
|
||||||
TupleList2 = lists:keyreplace(certfile, 1, TupleList1, {certfile, Certfile}),
|
|
||||||
TupleList3 =
|
|
||||||
case SslType of
|
|
||||||
ssl_twoway ->
|
|
||||||
CAfile = app_path(emqx, proplists:get_value(cacertfile, ?MQTT_SSL_TWOWAY)),
|
|
||||||
MutSslList = lists:keyreplace(
|
|
||||||
cacertfile, 1, ?MQTT_SSL_TWOWAY, {cacertfile, CAfile}
|
|
||||||
),
|
|
||||||
lists:merge(TupleList2, MutSslList);
|
|
||||||
_ ->
|
|
||||||
lists:filter(
|
|
||||||
fun
|
|
||||||
({cacertfile, _}) -> false;
|
|
||||||
({verify, _}) -> false;
|
|
||||||
({fail_if_no_peer_cert, _}) -> false;
|
|
||||||
(_) -> true
|
|
||||||
end,
|
|
||||||
TupleList2
|
|
||||||
)
|
|
||||||
end,
|
|
||||||
TupleList4 = emqx_misc:merge_opts(TupleList3, proplists:get_value(ssl_options, MoreOpts, [])),
|
|
||||||
NMoreOpts = emqx_misc:merge_opts(MoreOpts, [{ssl_options, TupleList4}]),
|
|
||||||
emqx_misc:merge_opts(Opts, NMoreOpts).
|
|
||||||
|
|
||||||
flush() ->
|
flush() ->
|
||||||
flush([]).
|
flush([]).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Copyright (c) 2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||||
|
%%
|
||||||
|
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
%% you may not use this file except in compliance with the License.
|
||||||
|
%% You may obtain a copy of the License at
|
||||||
|
%%
|
||||||
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
%%
|
||||||
|
%% Unless required by applicable law or agreed to in writing, software
|
||||||
|
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
%% See the License for the specific language governing permissions and
|
||||||
|
%% limitations under the License.
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(emqx_authn_enable_flag_SUITE).
|
||||||
|
|
||||||
|
-compile(export_all).
|
||||||
|
-compile(nowarn_export_all).
|
||||||
|
|
||||||
|
-include("emqx_authn.hrl").
|
||||||
|
|
||||||
|
-define(PATH, [?CONF_NS_ATOM]).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
all() ->
|
||||||
|
emqx_common_test_helpers:all(?MODULE).
|
||||||
|
|
||||||
|
init_per_suite(Config) ->
|
||||||
|
emqx_common_test_helpers:start_apps([emqx_conf, emqx_authn]),
|
||||||
|
Config.
|
||||||
|
|
||||||
|
end_per_suite(_) ->
|
||||||
|
emqx_common_test_helpers:stop_apps([emqx_authn, emqx_conf]),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
init_per_testcase(_Case, Config) ->
|
||||||
|
AuthnConfig = #{
|
||||||
|
<<"mechanism">> => <<"password_based">>,
|
||||||
|
<<"backend">> => <<"built_in_database">>,
|
||||||
|
<<"user_id_type">> => <<"clientid">>
|
||||||
|
},
|
||||||
|
emqx:update_config(
|
||||||
|
?PATH,
|
||||||
|
{create_authenticator, ?GLOBAL, AuthnConfig}
|
||||||
|
),
|
||||||
|
|
||||||
|
emqx_conf:update(
|
||||||
|
[listeners, tcp, listener_authn_enabled], {create, listener_mqtt_tcp_conf(18830, true)}, #{}
|
||||||
|
),
|
||||||
|
emqx_conf:update(
|
||||||
|
[listeners, tcp, listener_authn_disabled],
|
||||||
|
{create, listener_mqtt_tcp_conf(18831, false)},
|
||||||
|
#{}
|
||||||
|
),
|
||||||
|
Config.
|
||||||
|
|
||||||
|
end_per_testcase(_Case, Config) ->
|
||||||
|
emqx_authn_test_lib:delete_authenticators(
|
||||||
|
?PATH,
|
||||||
|
?GLOBAL
|
||||||
|
),
|
||||||
|
emqx_conf:remove(
|
||||||
|
[listeners, tcp, listener_authn_enabled], #{}
|
||||||
|
),
|
||||||
|
emqx_conf:remove(
|
||||||
|
[listeners, tcp, listener_authn_disabled], #{}
|
||||||
|
),
|
||||||
|
Config.
|
||||||
|
|
||||||
|
listener_mqtt_tcp_conf(Port, EnableAuthn) ->
|
||||||
|
#{
|
||||||
|
acceptors => 16,
|
||||||
|
zone => default,
|
||||||
|
access_rules => ["allow all"],
|
||||||
|
bind => {{0, 0, 0, 0}, Port},
|
||||||
|
max_connections => 1024000,
|
||||||
|
mountpoint => <<>>,
|
||||||
|
proxy_protocol => false,
|
||||||
|
proxy_protocol_timeout => 3000,
|
||||||
|
enable_authn => EnableAuthn
|
||||||
|
}.
|
||||||
|
|
||||||
|
t_enable_authn(_Config) ->
|
||||||
|
%% enable_authn set to false, we connect successfully
|
||||||
|
{ok, ConnPid0} = emqtt:start_link([{port, 18831}, {clientid, <<"clientid">>}]),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, _},
|
||||||
|
emqtt:connect(ConnPid0)
|
||||||
|
),
|
||||||
|
ok = emqtt:disconnect(ConnPid0),
|
||||||
|
|
||||||
|
process_flag(trap_exit, true),
|
||||||
|
|
||||||
|
%% enable_authn set to true, we go to the set up authn and fail
|
||||||
|
{ok, ConnPid1} = emqtt:start_link([{port, 18830}, {clientid, <<"clientid">>}]),
|
||||||
|
?assertMatch(
|
||||||
|
{error, {unauthorized_client, _}},
|
||||||
|
emqtt:connect(ConnPid1)
|
||||||
|
),
|
||||||
|
ok.
|
|
@ -84,8 +84,8 @@ t_create_invalid(_Config) ->
|
||||||
|
|
||||||
InvalidConfigs =
|
InvalidConfigs =
|
||||||
[
|
[
|
||||||
AuthConfig#{headers => []},
|
AuthConfig#{<<"headers">> => []},
|
||||||
AuthConfig#{method => delete}
|
AuthConfig#{<<"method">> => <<"delete">>}
|
||||||
],
|
],
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -181,7 +181,7 @@ t_destroy(_Config) ->
|
||||||
t_update(_Config) ->
|
t_update(_Config) ->
|
||||||
CorrectConfig = raw_http_auth_config(),
|
CorrectConfig = raw_http_auth_config(),
|
||||||
IncorrectConfig =
|
IncorrectConfig =
|
||||||
CorrectConfig#{url => <<"http://127.0.0.1:32333/invalid">>},
|
CorrectConfig#{<<"url">> => <<"http://127.0.0.1:32333/invalid">>},
|
||||||
|
|
||||||
{ok, _} = emqx:update_config(
|
{ok, _} = emqx:update_config(
|
||||||
?PATH,
|
?PATH,
|
||||||
|
@ -265,14 +265,14 @@ test_is_superuser({Kind, Value, ExpectedValue}) ->
|
||||||
|
|
||||||
raw_http_auth_config() ->
|
raw_http_auth_config() ->
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"http">>,
|
<<"backend">> => <<"http">>,
|
||||||
method => <<"get">>,
|
<<"method">> => <<"get">>,
|
||||||
url => <<"http://127.0.0.1:32333/auth">>,
|
<<"url">> => <<"http://127.0.0.1:32333/auth">>,
|
||||||
body => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
|
<<"body">> => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
|
||||||
headers => #{<<"X-Test-Header">> => <<"Test Value">>}
|
<<"headers">> => #{<<"X-Test-Header">> => <<"Test Value">>}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
samples() ->
|
samples() ->
|
||||||
|
@ -355,8 +355,8 @@ samples() ->
|
||||||
{ok, Req, State}
|
{ok, Req, State}
|
||||||
end,
|
end,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
method => post,
|
<<"method">> => <<"post">>,
|
||||||
headers => #{<<"content-type">> => <<"application/json">>}
|
<<"headers">> => #{<<"content-type">> => <<"application/json">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -373,8 +373,8 @@ samples() ->
|
||||||
{ok, Req, State}
|
{ok, Req, State}
|
||||||
end,
|
end,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
method => post,
|
<<"method">> => <<"post">>,
|
||||||
headers => #{
|
<<"headers">> => #{
|
||||||
<<"content-type">> =>
|
<<"content-type">> =>
|
||||||
<<"application/x-www-form-urlencoded">>
|
<<"application/x-www-form-urlencoded">>
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,18 +140,18 @@ create_https_auth_with_ssl_opts(SpecificSSLOpts) ->
|
||||||
raw_https_auth_config(SpecificSSLOpts) ->
|
raw_https_auth_config(SpecificSSLOpts) ->
|
||||||
SSLOpts = maps:merge(
|
SSLOpts = maps:merge(
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
emqx_authn_test_lib:client_ssl_cert_opts(),
|
||||||
#{enable => <<"true">>}
|
#{<<"enable">> => <<"true">>}
|
||||||
),
|
),
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"http">>,
|
<<"backend">> => <<"http">>,
|
||||||
method => <<"get">>,
|
<<"method">> => <<"get">>,
|
||||||
url => <<"https://127.0.0.1:32334/auth">>,
|
<<"url">> => <<"https://127.0.0.1:32334/auth">>,
|
||||||
body => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
|
<<"body">> => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
|
||||||
headers => #{<<"X-Test-Header">> => <<"Test Value">>},
|
<<"headers">> => #{<<"X-Test-Header">> => <<"Test Value">>},
|
||||||
ssl => maps:merge(SSLOpts, SpecificSSLOpts)
|
<<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
start_apps(Apps) ->
|
start_apps(Apps) ->
|
||||||
|
|
|
@ -492,14 +492,14 @@ generate_jws('public-key', Payload, PrivateKey) ->
|
||||||
JWS.
|
JWS.
|
||||||
|
|
||||||
client_ssl_opts() ->
|
client_ssl_opts() ->
|
||||||
maps:merge(
|
#{
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
keyfile => cert_file("client.key"),
|
||||||
#{
|
certfile => cert_file("client.crt"),
|
||||||
enable => true,
|
cacertfile => cert_file("ca.crt"),
|
||||||
verify => verify_peer,
|
enable => true,
|
||||||
server_name_indication => "authn-server"
|
verify => verify_peer,
|
||||||
}
|
server_name_indication => "authn-server"
|
||||||
).
|
}.
|
||||||
|
|
||||||
server_ssl_opts() ->
|
server_ssl_opts() ->
|
||||||
[
|
[
|
||||||
|
|
|
@ -83,9 +83,9 @@ t_create_invalid(_Config) ->
|
||||||
|
|
||||||
InvalidConfigs =
|
InvalidConfigs =
|
||||||
[
|
[
|
||||||
AuthConfig#{mongo_type => <<"unknown">>},
|
AuthConfig#{<<"mongo_type">> => <<"unknown">>},
|
||||||
AuthConfig#{filter => <<"{ \"username\": \"${username}\" }">>},
|
AuthConfig#{<<"filter">> => <<"{ \"username\": \"${username}\" }">>},
|
||||||
AuthConfig#{w_mode => <<"unknown">>}
|
AuthConfig#{<<"w_mode">> => <<"unknown">>}
|
||||||
],
|
],
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -180,7 +180,7 @@ t_update(_Config) ->
|
||||||
ok = init_seeds(),
|
ok = init_seeds(),
|
||||||
CorrectConfig = raw_mongo_auth_config(),
|
CorrectConfig = raw_mongo_auth_config(),
|
||||||
IncorrectConfig =
|
IncorrectConfig =
|
||||||
CorrectConfig#{filter => #{<<"wrongfield">> => <<"wrongvalue">>}},
|
CorrectConfig#{<<"filter">> => #{<<"wrongfield">> => <<"wrongvalue">>}},
|
||||||
|
|
||||||
{ok, _} = emqx:update_config(
|
{ok, _} = emqx:update_config(
|
||||||
?PATH,
|
?PATH,
|
||||||
|
@ -265,24 +265,24 @@ test_is_superuser({Value, ExpectedValue}) ->
|
||||||
|
|
||||||
raw_mongo_auth_config() ->
|
raw_mongo_auth_config() ->
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"mongodb">>,
|
<<"backend">> => <<"mongodb">>,
|
||||||
mongo_type => <<"single">>,
|
<<"mongo_type">> => <<"single">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
collection => <<"users">>,
|
<<"collection">> => <<"users">>,
|
||||||
server => mongo_server(),
|
<<"server">> => mongo_server(),
|
||||||
w_mode => <<"unsafe">>,
|
<<"w_mode">> => <<"unsafe">>,
|
||||||
|
|
||||||
filter => #{<<"username">> => <<"${username}">>},
|
<<"filter">> => #{<<"username">> => <<"${username}">>},
|
||||||
password_hash_field => <<"password_hash">>,
|
<<"password_hash_field">> => <<"password_hash">>,
|
||||||
salt_field => <<"salt">>,
|
<<"salt_field">> => <<"salt">>,
|
||||||
is_superuser_field => <<"is_superuser">>
|
<<"is_superuser_field">> => <<"is_superuser">>
|
||||||
}.
|
}.
|
||||||
|
|
||||||
user_seeds() ->
|
user_seeds() ->
|
||||||
|
@ -314,9 +314,9 @@ user_seeds() ->
|
||||||
password => <<"md5">>
|
password => <<"md5">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"md5">>,
|
<<"name">> => <<"md5">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
|
@ -335,10 +335,10 @@ user_seeds() ->
|
||||||
password => <<"sha256">>
|
password => <<"sha256">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
filter => #{<<"username">> => <<"${clientid}">>},
|
<<"filter">> => #{<<"username">> => <<"${clientid}">>},
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"sha256">>,
|
<<"name">> => <<"sha256">>,
|
||||||
salt_position => <<"prefix">>
|
<<"salt_position">> => <<"prefix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => true}}
|
result => {ok, #{is_superuser => true}}
|
||||||
|
@ -357,7 +357,7 @@ user_seeds() ->
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -376,8 +376,8 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% clientid variable & username credentials
|
% clientid variable & username credentials
|
||||||
filter => #{<<"username">> => <<"${clientid}">>},
|
<<"filter">> => #{<<"username">> => <<"${clientid}">>},
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -395,8 +395,8 @@ user_seeds() ->
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
filter => #{<<"userid">> => <<"${clientid}">>},
|
<<"filter">> => #{<<"userid">> => <<"${clientid}">>},
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -415,7 +415,7 @@ user_seeds() ->
|
||||||
password => <<"wrongpass">>
|
password => <<"wrongpass">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, bad_username_or_password}
|
result => {error, bad_username_or_password}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,33 +171,33 @@ create_mongo_auth_with_ssl_opts(SpecificSSLOpts) ->
|
||||||
raw_mongo_auth_config(SpecificSSLOpts) ->
|
raw_mongo_auth_config(SpecificSSLOpts) ->
|
||||||
SSLOpts = maps:merge(
|
SSLOpts = maps:merge(
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
emqx_authn_test_lib:client_ssl_cert_opts(),
|
||||||
#{enable => <<"true">>}
|
#{<<"enable">> => <<"true">>}
|
||||||
),
|
),
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"mongodb">>,
|
<<"backend">> => <<"mongodb">>,
|
||||||
pool_size => 2,
|
<<"pool_size">> => 2,
|
||||||
mongo_type => <<"single">>,
|
<<"mongo_type">> => <<"single">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
collection => <<"users">>,
|
<<"collection">> => <<"users">>,
|
||||||
server => mongo_server(),
|
<<"server">> => mongo_server(),
|
||||||
w_mode => <<"unsafe">>,
|
<<"w_mode">> => <<"unsafe">>,
|
||||||
|
|
||||||
filter => #{<<"username">> => <<"${username}">>},
|
<<"filter">> => #{<<"username">> => <<"${username}">>},
|
||||||
password_hash_field => <<"password_hash">>,
|
<<"password_hash_field">> => <<"password_hash">>,
|
||||||
salt_field => <<"salt">>,
|
<<"salt_field">> => <<"salt">>,
|
||||||
is_superuser_field => <<"is_superuser">>,
|
<<"is_superuser_field">> => <<"is_superuser">>,
|
||||||
topology => #{
|
<<"topology">> => #{
|
||||||
server_selection_timeout_ms => <<"10000ms">>
|
<<"server_selection_timeout_ms">> => <<"10000ms">>
|
||||||
},
|
},
|
||||||
|
|
||||||
ssl => maps:merge(SSLOpts, SpecificSSLOpts)
|
<<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
mongo_server() ->
|
mongo_server() ->
|
||||||
|
|
|
@ -100,10 +100,10 @@ t_create_invalid(_Config) ->
|
||||||
|
|
||||||
InvalidConfigs =
|
InvalidConfigs =
|
||||||
[
|
[
|
||||||
maps:without([server], AuthConfig),
|
maps:without([<<"server">>], AuthConfig),
|
||||||
AuthConfig#{server => <<"unknownhost:3333">>},
|
AuthConfig#{<<"server">> => <<"unknownhost:3333">>},
|
||||||
AuthConfig#{password => <<"wrongpass">>},
|
AuthConfig#{<<"password">> => <<"wrongpass">>},
|
||||||
AuthConfig#{database => <<"wrongdatabase">>}
|
AuthConfig#{<<"database">> => <<"wrongdatabase">>}
|
||||||
],
|
],
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -194,7 +194,7 @@ t_update(_Config) ->
|
||||||
CorrectConfig = raw_mysql_auth_config(),
|
CorrectConfig = raw_mysql_auth_config(),
|
||||||
IncorrectConfig =
|
IncorrectConfig =
|
||||||
CorrectConfig#{
|
CorrectConfig#{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
||||||
" FROM wrong_table where username = ${username} LIMIT 1"
|
" FROM wrong_table where username = ${username} LIMIT 1"
|
||||||
|
@ -236,24 +236,24 @@ t_update(_Config) ->
|
||||||
|
|
||||||
raw_mysql_auth_config() ->
|
raw_mysql_auth_config() ->
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"mysql">>,
|
<<"backend">> => <<"mysql">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
username => <<"root">>,
|
<<"username">> => <<"root">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
|
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
server => mysql_server()
|
<<"server">> => mysql_server()
|
||||||
}.
|
}.
|
||||||
|
|
||||||
user_seeds() ->
|
user_seeds() ->
|
||||||
|
@ -285,9 +285,9 @@ user_seeds() ->
|
||||||
password => <<"md5">>
|
password => <<"md5">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"md5">>,
|
<<"name">> => <<"md5">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
|
@ -305,14 +305,14 @@ user_seeds() ->
|
||||||
password => <<"sha256">>
|
password => <<"sha256">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${clientid} LIMIT 1"
|
" FROM users where username = ${clientid} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"sha256">>,
|
<<"name">> => <<"sha256">>,
|
||||||
salt_position => <<"prefix">>
|
<<"salt_position">> => <<"prefix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => true}}
|
result => {ok, #{is_superuser => true}}
|
||||||
|
@ -330,12 +330,12 @@ user_seeds() ->
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -351,12 +351,12 @@ user_seeds() ->
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -374,12 +374,12 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% clientid variable & username credentials
|
% clientid variable & username credentials
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${clientid} LIMIT 1"
|
" FROM users where username = ${clientid} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -397,12 +397,12 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% Bad keys in query
|
% Bad keys in query
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT 1 AS unknown_field\n"
|
"SELECT 1 AS unknown_field\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -420,7 +420,7 @@ user_seeds() ->
|
||||||
password => <<"wrongpass">>
|
password => <<"wrongpass">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, bad_username_or_password}
|
result => {error, bad_username_or_password}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,28 +131,28 @@ create_mysql_auth_with_ssl_opts(SpecificSSLOpts) ->
|
||||||
raw_mysql_auth_config(SpecificSSLOpts) ->
|
raw_mysql_auth_config(SpecificSSLOpts) ->
|
||||||
SSLOpts = maps:merge(
|
SSLOpts = maps:merge(
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
emqx_authn_test_lib:client_ssl_cert_opts(),
|
||||||
#{enable => <<"true">>}
|
#{<<"enable">> => <<"true">>}
|
||||||
),
|
),
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"mysql">>,
|
<<"backend">> => <<"mysql">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
username => <<"root">>,
|
<<"username">> => <<"root">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
|
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
server => mysql_server(),
|
<<"server">> => mysql_server(),
|
||||||
ssl => maps:merge(SSLOpts, SpecificSSLOpts)
|
<<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
mysql_server() ->
|
mysql_server() ->
|
||||||
|
|
|
@ -101,10 +101,10 @@ t_create_invalid(_Config) ->
|
||||||
|
|
||||||
InvalidConfigs =
|
InvalidConfigs =
|
||||||
[
|
[
|
||||||
maps:without([server], AuthConfig),
|
maps:without([<<"server">>], AuthConfig),
|
||||||
AuthConfig#{server => <<"unknownhost:3333">>},
|
AuthConfig#{<<"server">> => <<"unknownhost:3333">>},
|
||||||
AuthConfig#{password => <<"wrongpass">>},
|
AuthConfig#{<<"password">> => <<"wrongpass">>},
|
||||||
AuthConfig#{database => <<"wrongdatabase">>}
|
AuthConfig#{<<"database">> => <<"wrongdatabase">>}
|
||||||
],
|
],
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -195,7 +195,7 @@ t_update(_Config) ->
|
||||||
CorrectConfig = raw_pgsql_auth_config(),
|
CorrectConfig = raw_pgsql_auth_config(),
|
||||||
IncorrectConfig =
|
IncorrectConfig =
|
||||||
CorrectConfig#{
|
CorrectConfig#{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 0"
|
" FROM users where username = ${username} LIMIT 0"
|
||||||
|
@ -274,7 +274,7 @@ test_is_superuser({Field, Value, ExpectedValue}) ->
|
||||||
" as is_superuser "
|
" as is_superuser "
|
||||||
"FROM users where username = ${username} LIMIT 1",
|
"FROM users where username = ${username} LIMIT 1",
|
||||||
|
|
||||||
Config = maps:put(query, Query, raw_pgsql_auth_config()),
|
Config = maps:put(<<"query">>, Query, raw_pgsql_auth_config()),
|
||||||
{ok, _} = emqx:update_config(
|
{ok, _} = emqx:update_config(
|
||||||
?PATH,
|
?PATH,
|
||||||
{update_authenticator, ?GLOBAL, <<"password_based:postgresql">>, Config}
|
{update_authenticator, ?GLOBAL, <<"password_based:postgresql">>, Config}
|
||||||
|
@ -298,24 +298,24 @@ test_is_superuser({Field, Value, ExpectedValue}) ->
|
||||||
|
|
||||||
raw_pgsql_auth_config() ->
|
raw_pgsql_auth_config() ->
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"postgresql">>,
|
<<"backend">> => <<"postgresql">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
username => <<"root">>,
|
<<"username">> => <<"root">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
|
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_str as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
server => pgsql_server()
|
<<"server">> => pgsql_server()
|
||||||
}.
|
}.
|
||||||
|
|
||||||
user_seeds() ->
|
user_seeds() ->
|
||||||
|
@ -347,9 +347,9 @@ user_seeds() ->
|
||||||
password => <<"md5">>
|
password => <<"md5">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"md5">>,
|
<<"name">> => <<"md5">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
|
@ -367,14 +367,14 @@ user_seeds() ->
|
||||||
password => <<"sha256">>
|
password => <<"sha256">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${clientid} LIMIT 1"
|
" FROM users where username = ${clientid} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"sha256">>,
|
<<"name">> => <<"sha256">>,
|
||||||
salt_position => <<"prefix">>
|
<<"salt_position">> => <<"prefix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => true}}
|
result => {ok, #{is_superuser => true}}
|
||||||
|
@ -392,12 +392,12 @@ user_seeds() ->
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -415,12 +415,12 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% clientid variable & username credentials
|
% clientid variable & username credentials
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
"SELECT password_hash, salt, is_superuser_int as is_superuser\n"
|
||||||
" FROM users where username = ${clientid} LIMIT 1"
|
" FROM users where username = ${clientid} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -438,12 +438,12 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% Bad keys in query
|
% Bad keys in query
|
||||||
query =>
|
<<"query">> =>
|
||||||
<<
|
<<
|
||||||
"SELECT 1 AS unknown_field\n"
|
"SELECT 1 AS unknown_field\n"
|
||||||
" FROM users where username = ${username} LIMIT 1"
|
" FROM users where username = ${username} LIMIT 1"
|
||||||
>>,
|
>>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -461,7 +461,7 @@ user_seeds() ->
|
||||||
password => <<"wrongpass">>
|
password => <<"wrongpass">>
|
||||||
},
|
},
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, bad_username_or_password}
|
result => {error, bad_username_or_password}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,24 +131,24 @@ create_pgsql_auth_with_ssl_opts(SpecificSSLOpts) ->
|
||||||
raw_pgsql_auth_config(SpecificSSLOpts) ->
|
raw_pgsql_auth_config(SpecificSSLOpts) ->
|
||||||
SSLOpts = maps:merge(
|
SSLOpts = maps:merge(
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
emqx_authn_test_lib:client_ssl_cert_opts(),
|
||||||
#{enable => <<"true">>}
|
#{<<"enable">> => <<"true">>}
|
||||||
),
|
),
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"postgresql">>,
|
<<"backend">> => <<"postgresql">>,
|
||||||
database => <<"mqtt">>,
|
<<"database">> => <<"mqtt">>,
|
||||||
username => <<"root">>,
|
<<"username">> => <<"root">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
|
|
||||||
query => <<"SELECT 1">>,
|
<<"query">> => <<"SELECT 1">>,
|
||||||
server => pgsql_server(),
|
<<"server">> => pgsql_server(),
|
||||||
ssl => maps:merge(SSLOpts, SpecificSSLOpts)
|
<<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
pgsql_server() ->
|
pgsql_server() ->
|
||||||
|
|
|
@ -102,16 +102,16 @@ t_create_invalid(_Config) ->
|
||||||
InvalidConfigs =
|
InvalidConfigs =
|
||||||
[
|
[
|
||||||
AuthConfig#{
|
AuthConfig#{
|
||||||
cmd => <<"MGET password_hash:${username} salt:${username}">>
|
<<"cmd">> => <<"MGET password_hash:${username} salt:${username}">>
|
||||||
},
|
},
|
||||||
AuthConfig#{
|
AuthConfig#{
|
||||||
cmd => <<"HMGET mqtt_user:${username} password_hash invalid_field">>
|
<<"cmd">> => <<"HMGET mqtt_user:${username} password_hash invalid_field">>
|
||||||
},
|
},
|
||||||
AuthConfig#{
|
AuthConfig#{
|
||||||
cmd => <<"HMGET mqtt_user:${username} salt is_superuser">>
|
<<"cmd">> => <<"HMGET mqtt_user:${username} salt is_superuser">>
|
||||||
},
|
},
|
||||||
AuthConfig#{
|
AuthConfig#{
|
||||||
cmd => <<"HGETALL mqtt_user:${username} salt is_superuser">>
|
<<"cmd">> => <<"HGETALL mqtt_user:${username} salt is_superuser">>
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -131,10 +131,10 @@ t_create_invalid(_Config) ->
|
||||||
|
|
||||||
InvalidConfigs1 =
|
InvalidConfigs1 =
|
||||||
[
|
[
|
||||||
maps:without([server], AuthConfig),
|
maps:without([<<"server">>], AuthConfig),
|
||||||
AuthConfig#{server => <<"unknownhost:3333">>},
|
AuthConfig#{<<"server">> => <<"unknownhost:3333">>},
|
||||||
AuthConfig#{password => <<"wrongpass">>},
|
AuthConfig#{<<"password">> => <<"wrongpass">>},
|
||||||
AuthConfig#{database => <<"5678">>}
|
AuthConfig#{<<"database">> => <<"5678">>}
|
||||||
],
|
],
|
||||||
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -225,7 +225,7 @@ t_update(_Config) ->
|
||||||
CorrectConfig = raw_redis_auth_config(),
|
CorrectConfig = raw_redis_auth_config(),
|
||||||
IncorrectConfig =
|
IncorrectConfig =
|
||||||
CorrectConfig#{
|
CorrectConfig#{
|
||||||
cmd => <<"HMGET invalid_key:${username} password_hash salt is_superuser">>
|
<<"cmd">> => <<"HMGET invalid_key:${username} password_hash salt is_superuser">>
|
||||||
},
|
},
|
||||||
|
|
||||||
{ok, _} = emqx:update_config(
|
{ok, _} = emqx:update_config(
|
||||||
|
@ -263,19 +263,19 @@ t_update(_Config) ->
|
||||||
|
|
||||||
raw_redis_auth_config() ->
|
raw_redis_auth_config() ->
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"redis">>,
|
<<"backend">> => <<"redis">>,
|
||||||
cmd => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
||||||
database => <<"1">>,
|
<<"database">> => <<"1">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
redis_type => <<"single">>,
|
<<"redis_type">> => <<"single">>,
|
||||||
server => redis_server()
|
<<"server">> => redis_server()
|
||||||
}.
|
}.
|
||||||
|
|
||||||
user_seeds() ->
|
user_seeds() ->
|
||||||
|
@ -307,9 +307,9 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:md5">>,
|
key => <<"mqtt_user:md5">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"md5">>,
|
<<"name">> => <<"md5">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
|
@ -328,10 +328,10 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:sha256">>,
|
key => <<"mqtt_user:sha256">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
cmd => <<"HMGET mqtt_user:${clientid} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_user:${clientid} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"sha256">>,
|
<<"name">> => <<"sha256">>,
|
||||||
salt_position => <<"prefix">>
|
<<"salt_position">> => <<"prefix">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => true}}
|
result => {ok, #{is_superuser => true}}
|
||||||
|
@ -349,10 +349,10 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:sha256_no_salt">>,
|
key => <<"mqtt_user:sha256_no_salt">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
cmd => <<"HMGET mqtt_user:${clientid} password_hash is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_user:${clientid} password_hash is_superuser">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"sha256">>,
|
<<"name">> => <<"sha256">>,
|
||||||
salt_position => <<"disable">>
|
<<"salt_position">> => <<"disable">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => true}}
|
result => {ok, #{is_superuser => true}}
|
||||||
|
@ -371,7 +371,7 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:bcrypt">>,
|
key => <<"mqtt_user:bcrypt">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
@ -387,10 +387,10 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:pbkdf2">>,
|
key => <<"mqtt_user:pbkdf2">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"pbkdf2">>,
|
<<"name">> => <<"pbkdf2">>,
|
||||||
iterations => 2,
|
<<"iterations">> => <<"2">>,
|
||||||
mac_fun => sha
|
<<"mac_fun">> => <<"sha">>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result => {ok, #{is_superuser => false}}
|
result => {ok, #{is_superuser => false}}
|
||||||
|
@ -409,8 +409,8 @@ user_seeds() ->
|
||||||
key => <<"mqtt_user:bcrypt0">>,
|
key => <<"mqtt_user:bcrypt0">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% clientid variable & username credentials
|
% clientid variable & username credentials
|
||||||
cmd => <<"HMGET mqtt_client:${clientid} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_client:${clientid} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -429,8 +429,8 @@ user_seeds() ->
|
||||||
key => <<"mqtt_user:bcrypt1">>,
|
key => <<"mqtt_user:bcrypt1">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% Bad key in cmd
|
% Bad key in cmd
|
||||||
cmd => <<"HMGET badkey:${username} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET badkey:${username} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, not_authorized}
|
result => {error, not_authorized}
|
||||||
},
|
},
|
||||||
|
@ -449,8 +449,8 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
key => <<"mqtt_user:bcrypt2">>,
|
key => <<"mqtt_user:bcrypt2">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
cmd => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
<<"password_hash_algorithm">> => #{<<"name">> => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {error, bad_username_or_password}
|
result => {error, bad_username_or_password}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,23 +130,23 @@ create_redis_auth_with_ssl_opts(SpecificSSLOpts) ->
|
||||||
raw_redis_auth_config(SpecificSSLOpts) ->
|
raw_redis_auth_config(SpecificSSLOpts) ->
|
||||||
SSLOpts = maps:merge(
|
SSLOpts = maps:merge(
|
||||||
emqx_authn_test_lib:client_ssl_cert_opts(),
|
emqx_authn_test_lib:client_ssl_cert_opts(),
|
||||||
#{enable => <<"true">>}
|
#{<<"enable">> => <<"true">>}
|
||||||
),
|
),
|
||||||
#{
|
#{
|
||||||
mechanism => <<"password_based">>,
|
<<"mechanism">> => <<"password_based">>,
|
||||||
password_hash_algorithm => #{
|
<<"password_hash_algorithm">> => #{
|
||||||
name => <<"plain">>,
|
<<"name">> => <<"plain">>,
|
||||||
salt_position => <<"suffix">>
|
<<"salt_position">> => <<"suffix">>
|
||||||
},
|
},
|
||||||
enable => <<"true">>,
|
<<"enable">> => <<"true">>,
|
||||||
|
|
||||||
backend => <<"redis">>,
|
<<"backend">> => <<"redis">>,
|
||||||
cmd => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
<<"cmd">> => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
||||||
database => <<"1">>,
|
<<"database">> => <<"1">>,
|
||||||
password => <<"public">>,
|
<<"password">> => <<"public">>,
|
||||||
server => redis_server(),
|
<<"server">> => redis_server(),
|
||||||
redis_type => <<"single">>,
|
<<"redis_type">> => <<"single">>,
|
||||||
ssl => maps:merge(SSLOpts, SpecificSSLOpts)
|
<<"ssl">> => maps:merge(SSLOpts, SpecificSSLOpts)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
redis_server() ->
|
redis_server() ->
|
||||||
|
|
|
@ -62,7 +62,7 @@ delete_config(ID) ->
|
||||||
client_ssl_cert_opts() ->
|
client_ssl_cert_opts() ->
|
||||||
Dir = code:lib_dir(emqx_authn, test),
|
Dir = code:lib_dir(emqx_authn, test),
|
||||||
#{
|
#{
|
||||||
keyfile => filename:join([Dir, "data/certs", "client.key"]),
|
<<"keyfile">> => filename:join([Dir, <<"data/certs">>, <<"client.key">>]),
|
||||||
certfile => filename:join([Dir, "data/certs", "client.crt"]),
|
<<"certfile">> => filename:join([Dir, <<"data/certs">>, <<"client.crt">>]),
|
||||||
cacertfile => filename:join([Dir, "data/certs", "ca.crt"])
|
<<"cacertfile">> => filename:join([Dir, <<"data/certs">>, <<"ca.crt">>])
|
||||||
}.
|
}.
|
||||||
|
|
|
@ -589,6 +589,15 @@ See: https://erlang.org/doc/man/inet.html#setopts-2"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gateway_common_listener_enable_authn {
|
||||||
|
desc {
|
||||||
|
en: """Set <code>true</code> (default) to enable client authentication on this listener.
|
||||||
|
When set to <code>false</code> clients will be allowed to connect without authentication."""
|
||||||
|
zh: """配置 <code>true</code> (默认值)启用客户端进行身份认证。
|
||||||
|
配置 <code>false</code> 时,将不对客户端做任何认证。"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gateway_common_listener_mountpoint {
|
gateway_common_listener_mountpoint {
|
||||||
desc {
|
desc {
|
||||||
en: """When publishing or subscribing, prefix all topics with a mountpoint string.
|
en: """When publishing or subscribing, prefix all topics with a mountpoint string.
|
||||||
|
|
|
@ -131,6 +131,7 @@ init(
|
||||||
) ->
|
) ->
|
||||||
Peercert = maps:get(peercert, ConnInfo, undefined),
|
Peercert = maps:get(peercert, ConnInfo, undefined),
|
||||||
Mountpoint = maps:get(mountpoint, Config, <<>>),
|
Mountpoint = maps:get(mountpoint, Config, <<>>),
|
||||||
|
EnableAuthn = maps:get(enable_authn, Config, true),
|
||||||
ListenerId =
|
ListenerId =
|
||||||
case maps:get(listener, Config, undefined) of
|
case maps:get(listener, Config, undefined) of
|
||||||
undefined -> undefined;
|
undefined -> undefined;
|
||||||
|
@ -148,6 +149,7 @@ init(
|
||||||
username => undefined,
|
username => undefined,
|
||||||
is_bridge => false,
|
is_bridge => false,
|
||||||
is_superuser => false,
|
is_superuser => false,
|
||||||
|
enable_authn => EnableAuthn,
|
||||||
mountpoint => Mountpoint
|
mountpoint => Mountpoint
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
|
@ -26,11 +26,9 @@
|
||||||
%% configuration, register devices and other common operations.
|
%% configuration, register devices and other common operations.
|
||||||
%%
|
%%
|
||||||
-type context() ::
|
-type context() ::
|
||||||
%% Gateway Name
|
|
||||||
#{
|
#{
|
||||||
|
%% Gateway Name
|
||||||
gwname := gateway_name(),
|
gwname := gateway_name(),
|
||||||
%% Authentication chains
|
|
||||||
auth := [emqx_authentication:chain_name()],
|
|
||||||
%% The ConnectionManager PID
|
%% The ConnectionManager PID
|
||||||
cm := pid()
|
cm := pid()
|
||||||
}.
|
}.
|
||||||
|
@ -67,9 +65,7 @@
|
||||||
-spec authenticate(context(), emqx_types:clientinfo()) ->
|
-spec authenticate(context(), emqx_types:clientinfo()) ->
|
||||||
{ok, emqx_types:clientinfo()}
|
{ok, emqx_types:clientinfo()}
|
||||||
| {error, any()}.
|
| {error, any()}.
|
||||||
authenticate(_Ctx = #{auth := _ChainNames}, ClientInfo0) when
|
authenticate(_Ctx, ClientInfo0) ->
|
||||||
is_list(_ChainNames)
|
|
||||||
->
|
|
||||||
ClientInfo = ClientInfo0#{zone => default},
|
ClientInfo = ClientInfo0#{zone => default},
|
||||||
case emqx_access_control:authenticate(ClientInfo) of
|
case emqx_access_control:authenticate(ClientInfo) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
|
|
|
@ -649,6 +649,14 @@ common_listener_opts() ->
|
||||||
}
|
}
|
||||||
)},
|
)},
|
||||||
{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_ATOM, authentication_schema()},
|
{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_ATOM, authentication_schema()},
|
||||||
|
{"enable_authn",
|
||||||
|
sc(
|
||||||
|
boolean(),
|
||||||
|
#{
|
||||||
|
desc => ?DESC(gateway_common_listener_enable_authn),
|
||||||
|
default => true
|
||||||
|
}
|
||||||
|
)},
|
||||||
{mountpoint,
|
{mountpoint,
|
||||||
sc(
|
sc(
|
||||||
binary(),
|
binary(),
|
||||||
|
|
|
@ -157,7 +157,12 @@ init(
|
||||||
undefined -> undefined;
|
undefined -> undefined;
|
||||||
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
||||||
end,
|
end,
|
||||||
ClientInfo = maps:put(listener, ListenerId, default_clientinfo(ConnInfo)),
|
EnableAuthn = maps:get(enable_authn, Options, true),
|
||||||
|
DefaultClientInfo = default_clientinfo(ConnInfo),
|
||||||
|
ClientInfo = DefaultClientInfo#{
|
||||||
|
listener => ListenerId,
|
||||||
|
enable_authn => EnableAuthn
|
||||||
|
},
|
||||||
Channel = #channel{
|
Channel = #channel{
|
||||||
ctx = Ctx,
|
ctx = Ctx,
|
||||||
gcli = #{channel => GRpcChann, pool_name => PoolName},
|
gcli = #{channel => GRpcChann, pool_name => PoolName},
|
||||||
|
|
|
@ -128,6 +128,7 @@ init(
|
||||||
undefined -> undefined;
|
undefined -> undefined;
|
||||||
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
||||||
end,
|
end,
|
||||||
|
EnableAuthn = maps:get(enable_authn, Config, true),
|
||||||
ClientInfo = set_peercert_infos(
|
ClientInfo = set_peercert_infos(
|
||||||
Peercert,
|
Peercert,
|
||||||
#{
|
#{
|
||||||
|
@ -140,6 +141,7 @@ init(
|
||||||
clientid => undefined,
|
clientid => undefined,
|
||||||
is_bridge => false,
|
is_bridge => false,
|
||||||
is_superuser => false,
|
is_superuser => false,
|
||||||
|
enable_authn => EnableAuthn,
|
||||||
mountpoint => Mountpoint
|
mountpoint => Mountpoint
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
|
@ -156,6 +156,7 @@ init(
|
||||||
undefined -> undefined;
|
undefined -> undefined;
|
||||||
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
||||||
end,
|
end,
|
||||||
|
EnableAuthn = maps:get(enable_authn, Option, true),
|
||||||
ClientInfo = set_peercert_infos(
|
ClientInfo = set_peercert_infos(
|
||||||
Peercert,
|
Peercert,
|
||||||
#{
|
#{
|
||||||
|
@ -168,6 +169,7 @@ init(
|
||||||
username => undefined,
|
username => undefined,
|
||||||
is_bridge => false,
|
is_bridge => false,
|
||||||
is_superuser => false,
|
is_superuser => false,
|
||||||
|
enable_authn => EnableAuthn,
|
||||||
mountpoint => Mountpoint
|
mountpoint => Mountpoint
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
|
@ -127,6 +127,7 @@ init(
|
||||||
undefined -> undefined;
|
undefined -> undefined;
|
||||||
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
{GwName, Type, LisName} -> emqx_gateway_utils:listener_id(GwName, Type, LisName)
|
||||||
end,
|
end,
|
||||||
|
EnableAuthn = maps:get(enable_authn, Option, true),
|
||||||
ClientInfo = setting_peercert_infos(
|
ClientInfo = setting_peercert_infos(
|
||||||
Peercert,
|
Peercert,
|
||||||
#{
|
#{
|
||||||
|
@ -139,6 +140,7 @@ init(
|
||||||
username => undefined,
|
username => undefined,
|
||||||
is_bridge => false,
|
is_bridge => false,
|
||||||
is_superuser => false,
|
is_superuser => false,
|
||||||
|
enable_authn => EnableAuthn,
|
||||||
mountpoint => Mountpoint
|
mountpoint => Mountpoint
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
|
@ -109,6 +109,12 @@ t_case_coap(_) ->
|
||||||
Prefix ++
|
Prefix ++
|
||||||
"/connection?clientid=client1&username=bad&password=bad",
|
"/connection?clientid=client1&username=bad&password=bad",
|
||||||
Login(LeftUrl, ?checkMatch({error, bad_request, _Data})),
|
Login(LeftUrl, ?checkMatch({error, bad_request, _Data})),
|
||||||
|
|
||||||
|
disable_authn(coap, udp, default),
|
||||||
|
NowRightUrl =
|
||||||
|
Prefix ++
|
||||||
|
"/connection?clientid=client1&username=bad&password=bad",
|
||||||
|
Login(NowRightUrl, ?checkMatch({ok, created, _Data})),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-record(coap_content, {content_format, payload = <<>>}).
|
-record(coap_content, {content_format, payload = <<>>}).
|
||||||
|
@ -155,6 +161,11 @@ t_case_lwm2m(_) ->
|
||||||
|
|
||||||
NoInfoUrl = "coap://127.0.0.1:~b/rd?ep=~ts<=345&lwm2m=1",
|
NoInfoUrl = "coap://127.0.0.1:~b/rd?ep=~ts<=345&lwm2m=1",
|
||||||
Login(NoInfoUrl, MakeCheker(ack, {error, bad_request})),
|
Login(NoInfoUrl, MakeCheker(ack, {error, bad_request})),
|
||||||
|
|
||||||
|
disable_authn(lwm2m, udp, default),
|
||||||
|
NowRightUrl = "coap://127.0.0.1:~b/rd?ep=~ts<=345&lwm2m=1&imei=bad&password=bad",
|
||||||
|
Login(NowRightUrl, MakeCheker(ack, {ok, created})),
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-define(SN_CONNACK, 16#05).
|
-define(SN_CONNACK, 16#05).
|
||||||
|
@ -182,6 +193,9 @@ t_case_mqttsn(_) ->
|
||||||
end,
|
end,
|
||||||
Login(<<"badadmin">>, <<"badpassowrd">>, <<3, ?SN_CONNACK, 16#80>>),
|
Login(<<"badadmin">>, <<"badpassowrd">>, <<3, ?SN_CONNACK, 16#80>>),
|
||||||
Login(<<"admin">>, <<"public">>, <<3, ?SN_CONNACK, 0>>),
|
Login(<<"admin">>, <<"public">>, <<3, ?SN_CONNACK, 0>>),
|
||||||
|
|
||||||
|
disable_authn(mqttsn, udp, default),
|
||||||
|
Login(<<"badadmin">>, <<"badpassowrd">>, <<3, ?SN_CONNACK, 0>>),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_case_stomp(_) ->
|
t_case_stomp(_) ->
|
||||||
|
@ -220,6 +234,15 @@ t_case_stomp(_) ->
|
||||||
?assertEqual(<<"Login Failed: not_authorized">>, Mod:get_field(body, Frame))
|
?assertEqual(<<"Login Failed: not_authorized">>, Mod:get_field(body, Frame))
|
||||||
end),
|
end),
|
||||||
|
|
||||||
|
disable_authn(stomp, tcp, default),
|
||||||
|
Login(
|
||||||
|
<<"bad">>,
|
||||||
|
<<"bad">>,
|
||||||
|
?FUNCTOR(
|
||||||
|
Frame,
|
||||||
|
?assertEqual(<<"CONNECTED">>, Mod:get_field(command, Frame))
|
||||||
|
)
|
||||||
|
),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_case_exproto(_) ->
|
t_case_exproto(_) ->
|
||||||
|
@ -249,5 +272,18 @@ t_case_exproto(_) ->
|
||||||
end,
|
end,
|
||||||
Login(<<"admin">>, <<"public">>, SvrMod:frame_connack(0)),
|
Login(<<"admin">>, <<"public">>, SvrMod:frame_connack(0)),
|
||||||
Login(<<"bad">>, <<"bad">>, SvrMod:frame_connack(1)),
|
Login(<<"bad">>, <<"bad">>, SvrMod:frame_connack(1)),
|
||||||
|
|
||||||
|
disable_authn(exproto, tcp, default),
|
||||||
|
Login(<<"bad">>, <<"bad">>, SvrMod:frame_connack(0)),
|
||||||
|
|
||||||
SvrMod:stop(Svrs),
|
SvrMod:stop(Svrs),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
disable_authn(GwName, Type, Name) ->
|
||||||
|
RawCfg = emqx_conf:get_raw([gateway, GwName], #{}),
|
||||||
|
ListenerCfg = emqx_map_lib:deep_get(
|
||||||
|
[<<"listeners">>, atom_to_binary(Type), atom_to_binary(Name)], RawCfg
|
||||||
|
),
|
||||||
|
{ok, _} = emqx_gateway_conf:update_listener(GwName, {Type, Name}, ListenerCfg#{
|
||||||
|
<<"enable_authn">> => false
|
||||||
|
}).
|
||||||
|
|
|
@ -50,7 +50,7 @@ end_per_suite(_Conf) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
t_authenticate(_) ->
|
t_authenticate(_) ->
|
||||||
Ctx = #{gwname => mqttsn, auth => [], cm => self()},
|
Ctx = #{gwname => mqttsn, cm => self()},
|
||||||
Info1 = #{
|
Info1 = #{
|
||||||
mountpoint => undefined,
|
mountpoint => undefined,
|
||||||
clientid => <<"user1">>
|
clientid => <<"user1">>
|
||||||
|
|
Loading…
Reference in New Issue