emqx/apps/emqx_management/test/emqx_mgmt_auth_api_SUITE.erl

187 lines
7.3 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2020-2021 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_mgmt_auth_api_SUITE).
-compile(export_all).
-compile(nowarn_export_all).
-include_lib("eunit/include/eunit.hrl").
all() -> [{group, parallel}, {group, sequence}].
suite() -> [{timetrap, {minutes, 1}}].
groups() -> [
{parallel, [parallel], [t_create, t_update, t_delete, t_authorize]},
{sequence, [], [t_create_failed]}
].
init_per_suite(Config) ->
emqx_mgmt_api_test_util:init_suite(),
Config.
end_per_suite(_) ->
emqx_mgmt_api_test_util:end_suite().
t_create(_Config) ->
Name = <<"EMQX-API-KEY-1">>,
{ok, Create} = create_app(Name),
?assertMatch(#{<<"api_key">> := _,
<<"api_secret">> := _,
<<"created_at">> := _,
<<"desc">> := _,
<<"enable">> := true,
<<"expired_at">> := _,
<<"name">> := Name}, Create),
{ok, List} = list_app(),
[App] = lists:filter(fun(#{<<"name">> := NameA}) -> NameA =:= Name end, List),
?assertEqual(false, maps:is_key(<<"api_secret">>, App)),
{ok, App1} = read_app(Name),
?assertEqual(Name, maps:get(<<"name">>, App1)),
?assertEqual(true, maps:get(<<"enable">>, App1)),
?assertEqual(false, maps:is_key(<<"api_secret">>, App1)),
?assertEqual({error, {"HTTP/1.1", 404, "Not Found"}}, read_app(<<"EMQX-API-KEY-NO-EXIST">>)),
ok.
t_create_failed(_Config) ->
BadRequest = {error, {"HTTP/1.1", 400, "Bad Request"}},
?assertEqual(BadRequest, create_app(<<" error format name">>)),
LongName = iolist_to_binary(lists:duplicate(257, "A")),
?assertEqual(BadRequest, create_app(<<" error format name">>)),
?assertEqual(BadRequest, create_app(LongName)),
{ok, List} = list_app(),
CreateNum = 30 - erlang:length(List),
Names = lists:map(fun(Seq) ->
<<"EMQX-API-FAILED-KEY-", (integer_to_binary(Seq))/binary>>
end, lists:seq(1, CreateNum)),
lists:foreach(fun(N) -> {ok, _} = create_app(N) end, Names),
?assertEqual(BadRequest, create_app(<<"EMQX-API-KEY-MAXIMUM">>)),
lists:foreach(fun(N) -> {ok, _} = delete_app(N) end, Names),
Name = <<"EMQX-API-FAILED-KEY-1">>,
?assertMatch({ok, _}, create_app(Name)),
?assertEqual(BadRequest, create_app(Name)),
{ok, _} = delete_app(Name),
?assertMatch({ok, #{<<"name">> := Name}}, create_app(Name)),
{ok, _} = delete_app(Name),
ok.
t_update(_Config) ->
Name = <<"EMQX-API-UPDATE-KEY">>,
{ok, _} = create_app(Name),
ExpiredAt = to_rfc3339(erlang:system_time(second) + 10000),
Change = #{
expired_at => ExpiredAt,
desc => <<"NoteVersion1"/utf8>>,
enable => false
},
{ok, Update1} = update_app(Name, Change),
?assertEqual(Name, maps:get(<<"name">>, Update1)),
?assertEqual(false, maps:get(<<"enable">>, Update1)),
?assertEqual(<<"NoteVersion1"/utf8>>, maps:get(<<"desc">>, Update1)),
?assertEqual(calendar:rfc3339_to_system_time(binary_to_list(ExpiredAt)),
calendar:rfc3339_to_system_time(binary_to_list(maps:get(<<"expired_at">>, Update1)))
),
?assertEqual({error, {"HTTP/1.1", 404, "Not Found"}}, update_app(<<"Not-Exist">>, Change)),
ok.
t_delete(_Config) ->
Name = <<"EMQX-API-DELETE-KEY">>,
{ok, _Create} = create_app(Name),
{ok, Delete} = delete_app(Name),
?assertEqual([], Delete),
?assertEqual({error, {"HTTP/1.1", 404, "Not Found"}}, delete_app(Name)),
ok.
t_authorize(_Config) ->
Name = <<"EMQX-API-AUTHORIZE-KEY">>,
{ok, #{<<"api_key">> := ApiKey, <<"api_secret">> := ApiSecret}} = create_app(Name),
BasicHeader = emqx_common_test_http:auth_header(binary_to_list(ApiKey),
binary_to_list(ApiSecret)),
SecretError = emqx_common_test_http:auth_header(binary_to_list(ApiKey),
binary_to_list(ApiKey)),
KeyError = emqx_common_test_http:auth_header("not_found_key", binary_to_list(ApiSecret)),
Unauthorized = {error, {"HTTP/1.1", 401, "Unauthorized"}},
BanPath = emqx_mgmt_api_test_util:api_path(["banned"]),
ApiKeyPath = emqx_mgmt_api_test_util:api_path(["api_key"]),
UserPath = emqx_mgmt_api_test_util:api_path(["users"]),
{ok, _Status} = emqx_mgmt_api_test_util:request_api(get, BanPath, BasicHeader),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, KeyError)),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, SecretError)),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, ApiKeyPath, BasicHeader)),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, UserPath, BasicHeader)),
?assertMatch({ok, #{<<"api_key">> := _, <<"enable">> := false}},
update_app(Name, #{enable => false})),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, BasicHeader)),
Expired = #{
expired_at => to_rfc3339(erlang:system_time(second) - 1),
enable => true
},
?assertMatch({ok, #{<<"api_key">> := _, <<"enable">> := true}}, update_app(Name, Expired)),
?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, BasicHeader)),
ok.
list_app() ->
Path = emqx_mgmt_api_test_util:api_path(["api_key"]),
case emqx_mgmt_api_test_util:request_api(get, Path) of
{ok, Apps} -> {ok, emqx_json:decode(Apps, [return_maps])};
Error -> Error
end.
read_app(Name) ->
Path = emqx_mgmt_api_test_util:api_path(["api_key", Name]),
case emqx_mgmt_api_test_util:request_api(get, Path) of
{ok, Res} -> {ok, emqx_json:decode(Res, [return_maps])};
Error -> Error
end.
create_app(Name) ->
AuthHeader = emqx_mgmt_api_test_util:auth_header_(),
Path = emqx_mgmt_api_test_util:api_path(["api_key"]),
ExpiredAt = to_rfc3339(erlang:system_time(second) + 1000),
App = #{
name => Name,
expired_at => ExpiredAt,
desc => <<"Note"/utf8>>,
enable => true
},
case emqx_mgmt_api_test_util:request_api(post, Path, "", AuthHeader, App) of
{ok, Res} -> {ok, emqx_json:decode(Res, [return_maps])};
Error -> Error
end.
delete_app(Name) ->
DeletePath = emqx_mgmt_api_test_util:api_path(["api_key", Name]),
emqx_mgmt_api_test_util:request_api(delete, DeletePath).
update_app(Name, Change) ->
AuthHeader = emqx_mgmt_api_test_util:auth_header_(),
UpdatePath = emqx_mgmt_api_test_util:api_path(["api_key", Name]),
case emqx_mgmt_api_test_util:request_api(put, UpdatePath, "", AuthHeader, Change) of
{ok, Update} -> {ok, emqx_json:decode(Update, [return_maps])};
Error -> Error
end.
to_rfc3339(Sec) ->
list_to_binary(calendar:system_time_to_rfc3339(Sec)).