emqx/apps/emqx/test/emqx_access_control_SUITE.erl

127 lines
4.5 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2019-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_access_control_SUITE).
-compile(export_all).
-compile(nowarn_export_all).
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx/include/emqx_hooks.hrl").
-include_lib("eunit/include/eunit.hrl").
all() -> emqx_common_test_helpers:all(?MODULE).
init_per_suite(Config) ->
emqx_common_test_helpers:boot_modules([router, broker]),
emqx_common_test_helpers:start_apps([]),
Config.
end_per_suite(_Config) ->
emqx_common_test_helpers:stop_apps([]).
init_per_testcase(_, Config) ->
Config.
end_per_testcase(_, _Config) ->
ok = emqx_hooks:del('client.authorize', {?MODULE, authz_stub}),
ok = emqx_hooks:del('client.authenticate', {?MODULE, quick_deny_anonymous_authn}).
t_authenticate(_) ->
?assertMatch({ok, _}, emqx_access_control:authenticate(clientinfo())).
t_authorize(_) ->
Publish = ?PUBLISH_PACKET(?QOS_0, <<"t">>, 1, <<"payload">>),
?assertEqual(allow, emqx_access_control:authorize(clientinfo(), Publish, <<"t">>)).
t_delayed_authorize(_) ->
RawTopic = <<"$delayed/1/foo/2">>,
InvalidTopic = <<"$delayed/1/foo/3">>,
Topic = <<"foo/2">>,
ok = emqx_hooks:put('client.authorize', {?MODULE, authz_stub, [Topic]}, ?HP_AUTHZ),
Publish1 = ?PUBLISH_PACKET(?QOS_0, RawTopic, 1, <<"payload">>),
?assertEqual(allow, emqx_access_control:authorize(clientinfo(), Publish1, RawTopic)),
Publish2 = ?PUBLISH_PACKET(?QOS_0, InvalidTopic, 1, <<"payload">>),
?assertEqual(deny, emqx_access_control:authorize(clientinfo(), Publish2, InvalidTopic)),
ok.
t_quick_deny_anonymous(_) ->
ok = emqx_hooks:put(
'client.authenticate',
{?MODULE, quick_deny_anonymous_authn, []},
?HP_AUTHN
),
RawClient0 = clientinfo(),
RawClient = RawClient0#{username => undefined},
%% No name, No authn
Client1 = RawClient#{enable_authn => false},
?assertMatch({ok, _}, emqx_access_control:authenticate(Client1)),
%% No name, With quick_deny_anonymous
Client2 = RawClient#{enable_authn => quick_deny_anonymous},
?assertMatch({error, _}, emqx_access_control:authenticate(Client2)),
%% Bad name, With quick_deny_anonymous
Client3 = RawClient#{enable_authn => quick_deny_anonymous, username => <<"badname">>},
?assertMatch({error, _}, emqx_access_control:authenticate(Client3)),
%% Good name, With quick_deny_anonymous
Client4 = RawClient#{enable_authn => quick_deny_anonymous, username => <<"goodname">>},
?assertMatch({ok, _}, emqx_access_control:authenticate(Client4)),
%% Name, With authn
Client5 = RawClient#{enable_authn => true, username => <<"badname">>},
?assertMatch({error, _}, emqx_access_control:authenticate(Client5)),
ok.
%%--------------------------------------------------------------------
%% Helper functions
%%--------------------------------------------------------------------
authz_stub(_Client, _PubSub, ValidTopic, _DefaultResult, ValidTopic) -> {stop, #{result => allow}};
authz_stub(_Client, _PubSub, _Topic, _DefaultResult, _ValidTopic) -> {stop, #{result => deny}}.
quick_deny_anonymous_authn(#{username := <<"badname">>}, _AuthResult) ->
{stop, {error, not_authorized}};
quick_deny_anonymous_authn(_ClientInfo, _AuthResult) ->
{stop, {ok, #{is_superuser => false}}}.
clientinfo() -> clientinfo(#{}).
clientinfo(InitProps) ->
maps:merge(
#{
zone => default,
listener => {tcp, default},
protocol => mqtt,
peerhost => {127, 0, 0, 1},
clientid => <<"clientid">>,
username => <<"username">>,
password => <<"passwd">>,
is_superuser => false,
peercert => undefined,
mountpoint => undefined
},
InitProps
).
toggle_auth(Bool) when is_boolean(Bool) ->
emqx_config:put_zone_conf(default, [auth, enable], Bool).