diff --git a/etc/emqx.conf b/etc/emqx.conf index d41d604c3..82ec0dc8c 100644 --- a/etc/emqx.conf +++ b/etc/emqx.conf @@ -29,7 +29,7 @@ cluster.proto_dist = inet_tcp ## - mcast: IP Multicast ## - dns: DNS A Record ## - etcd: etcd -## - k8s: Kubernates +## - k8s: Kubernetes ## ## Default: manual cluster.discovery = manual @@ -141,9 +141,9 @@ cluster.autoclean = 5m ## cluster.etcd.ssl.cacertfile = {{ platform_etc_dir }}/certs/ca.pem ##-------------------------------------------------------------------- -## Cluster using Kubernates +## Cluster using Kubernetes -## Kubernates API server list, seperated by ','. +## Kubernetes API server list, seperated by ','. ## ## Value: String ## cluster.k8s.apiserver = http://10.110.111.204:8080 @@ -168,7 +168,7 @@ cluster.autoclean = 5m ## Value: String ## cluster.k8s.suffix = pod.cluster.local -## Kubernates Namespace +## Kubernetes Namespace ## ## Value: String ## cluster.k8s.namespace = default @@ -849,6 +849,11 @@ zone.internal.ignore_loop_deliver = false ## Value: true | false zone.internal.strict_mode = false +## Allow the zone's clients to bypass authentication step +## +## Value: true | false +zone.internal.bypass_auth_plugins = true + ##-------------------------------------------------------------------- ## Listeners ##-------------------------------------------------------------------- diff --git a/priv/emqx.schema b/priv/emqx.schema index 468dfc343..db4421c91 100644 --- a/priv/emqx.schema +++ b/priv/emqx.schema @@ -939,6 +939,12 @@ end}. {datatype, {enum, [true, false]}} ]}. +%% @doc Whether to bypass the authentication step +{mapping, "zone.$name.bypass_auth_plugins", "emqx.zones", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + {translation, "emqx.zones", fun(Conf) -> Mapping = fun("publish_limit", Val) -> [L, D] = string:tokens(Val, ", "), diff --git a/src/emqx_access_control.erl b/src/emqx_access_control.erl index 4ee62a42e..e891ca275 100644 --- a/src/emqx_access_control.erl +++ b/src/emqx_access_control.erl @@ -34,11 +34,12 @@ -spec(authenticate(emqx_types:clientinfo()) -> {ok, result()} | {error, term()}). authenticate(ClientInfo = #{zone := Zone}) -> - case run_hooks('client.authenticate', [ClientInfo], default_auth_result(Zone)) of - Result = #{auth_result := success} -> - {ok, Result}; - Result -> - {error, maps:get(auth_result, Result, unknown_error)} + AuthResult = default_auth_result(Zone), + case emqx_zone:get_env(Zone, bypass_auth_plugins, false) of + true -> + return_auth_result(AuthResult); + false -> + return_auth_result(run_hooks('client.authenticate', [ClientInfo], AuthResult)) end. %% @doc Check ACL @@ -81,3 +82,8 @@ default_auth_result(Zone) -> run_hooks(Name, Args, Acc) -> ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc). +-compile({inline, [return_auth_result/1]}). +return_auth_result(Result = #{auth_result := success}) -> + {ok, Result}; +return_auth_result(Result) -> + {error, maps:get(auth_result, Result, unknown_error)}. diff --git a/src/emqx_cm.erl b/src/emqx_cm.erl index 8bc2fbd07..dd8b02e54 100644 --- a/src/emqx_cm.erl +++ b/src/emqx_cm.erl @@ -273,6 +273,8 @@ discard_session(ClientId) when is_binary(ClientId) -> try discard_session(ClientId, ChanPid) catch + _:{noproc,_}:_Stk -> ok; + _:{{shutdown,_},_}:_Stk -> ok; _:Error:_Stk -> ?LOG(error, "Failed to discard ~p: ~p", [ChanPid, Error]) end diff --git a/src/emqx_json.erl b/src/emqx_json.erl index c81c9b06b..93243f7ac 100644 --- a/src/emqx_json.erl +++ b/src/emqx_json.erl @@ -103,7 +103,7 @@ safe_decode(Json, Opts) -> , from_ejson/1 ]}). -to_ejson([[{_,_}]|_] = L) -> +to_ejson([[{_,_}|_]|_] = L) -> [to_ejson(E) || E <- L]; to_ejson([{_, _}|_] = L) -> lists:foldl( diff --git a/test/emqx_access_control_SUITE.erl b/test/emqx_access_control_SUITE.erl index 34a0b83b1..ca4db1fbb 100644 --- a/test/emqx_access_control_SUITE.erl +++ b/test/emqx_access_control_SUITE.erl @@ -52,6 +52,20 @@ t_check_acl(_) -> t_reload_acl(_) -> ?assertEqual(ok, emqx_access_control:reload_acl()). +t_bypass_auth_plugins(_) -> + AuthFun = fun(#{zone := bypass_zone}, AuthRes) -> + {stop, AuthRes#{auth_result => password_error}}; + (#{zone := _}, AuthRes) -> + {stop, AuthRes#{auth_result => success}} + end, + ClientInfo = clientinfo(), + emqx_zone:set_env(bypass_zone, allow_anonymous, true), + emqx_zone:set_env(zone, allow_anonymous, false), + emqx_zone:set_env(bypass_zone, bypass_auth_plugins, true), + emqx:hook('client.authenticate', AuthFun, []), + ?assertMatch({ok, _}, emqx_access_control:authenticate(ClientInfo#{zone => bypass_zone})), + ?assertMatch({ok, _}, emqx_access_control:authenticate(ClientInfo)). + %%-------------------------------------------------------------------- %% Helper functions %%-------------------------------------------------------------------- diff --git a/test/emqx_json_SUITE.erl b/test/emqx_json_SUITE.erl index 434180cb9..67f8108c5 100644 --- a/test/emqx_json_SUITE.erl +++ b/test/emqx_json_SUITE.erl @@ -68,6 +68,11 @@ t_decode_encode(_) -> [{<<"foo">>, <<"bar">>}] = decode(encode({[{<<"foo">>, <<"bar">>}]})), [{<<"foo">>, <<"bar">>}] = decode(encode([{<<"foo">>, <<"bar">>}])), [[{<<"foo">>, <<"bar">>}]] = decode(encode([[{<<"foo">>, <<"bar">>}]])), + [[{<<"foo">>, <<"bar">>}, + {<<"a">>, <<"b">>}], + [{<<"x">>, <<"y">>}]] = decode(encode([[{<<"foo">>, <<"bar">>}, + {<<"a">>, <<"b">>}], + [{<<"x">>, <<"y">>}]])), #{<<"foo">> := <<"bar">>} = decode(encode(#{<<"foo">> => <<"bar">>}), [return_maps]), JsonText = <<"{\"bool\":true,\"int\":10,\"foo\":\"bar\"}">>, JsonMaps = #{<<"bool">> => true, diff --git a/test/emqx_logger_formatter_SUITE.erl b/test/emqx_logger_formatter_SUITE.erl index 6699ae68c..3d7469dca 100644 --- a/test/emqx_logger_formatter_SUITE.erl +++ b/test/emqx_logger_formatter_SUITE.erl @@ -20,6 +20,7 @@ -module(emqx_logger_formatter_SUITE). -compile(export_all). +-compile(nowarn_export_all). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl").