chore: add more test for api_key

This commit is contained in:
Zhongwen Deng 2023-01-10 18:39:05 +08:00
parent f6a47e5cf6
commit 5d4a1933a2
3 changed files with 57 additions and 230 deletions

View File

@ -1,221 +0,0 @@
emqx_dashboard_schema {
listeners {
desc {
en: """HTTP(s) listeners are identified by their protocol type and are
used to serve dashboard UI and restful HTTP API.
Listeners must have a unique combination of port number and IP address.
For example, an HTTP listener can listen on all configured IP addresses
on a given port for a machine by specifying the IP address 0.0.0.0.
Alternatively, the HTTP listener can specify a unique IP address for each listener,
but use the same port."""
zh: """仪表盘监听器设置。"""
}
label {
en: "Listeners"
zh: "监听器"
}
}
sample_interval {
desc {
en: """How often to update metrics displayed in the dashboard.
Note: `sample_interval` should be a divisor of 60."""
zh: """更新仪表板中显示的指标的时间间隔。必须小于60且被60的整除。"""
}
}
token_expired_time {
desc {
en: "JWT token expiration time."
zh: "JWT token 过期时间"
}
label {
en: "Token expired time"
zh: "JWT 过期时间"
}
}
num_acceptors {
desc {
en: "Socket acceptor pool size for TCP protocols."
zh: "TCP协议的Socket acceptor池大小"
}
label {
en: "Number of acceptors"
zh: "Acceptor 数量"
}
}
max_connections {
desc {
en: "Maximum number of simultaneous connections."
zh: "同时处理的最大连接数"
}
label {
en: "Maximum connections"
zh: "最大连接数"
}
}
backlog {
desc {
en: "Defines the maximum length that the queue of pending connections can grow to."
zh: "排队等待连接的队列的最大长度"
}
label {
en: "Backlog"
zh: "排队长度"
}
}
send_timeout {
desc {
en: "Send timeout for the socket."
zh: "Socket发送超时时间"
}
label {
en: "Send timeout"
zh: "发送超时时间"
}
}
inet6 {
desc {
en: "Enable IPv6 support, default is false, which means IPv4 only."
zh: "启用IPv6 如果机器不支持IPv6请关闭此选项否则会导致仪表盘无法使用。"
}
label {
en: "IPv6"
zh: "IPv6"
}
}
ipv6_v6only {
desc {
en: "Disable IPv4-to-IPv6 mapping for the listener."
zh: "当开启 inet6 功能的同时禁用 IPv4-to-IPv6 映射。该配置仅在 inet6 功能开启时有效。"
}
label {
en: "IPv6 only"
zh: "IPv6 only"
}
}
desc_dashboard {
desc {
en: "Configuration for EMQX dashboard."
zh: "EMQX仪表板配置"
}
label {
en: "Dashboard"
zh: "仪表板"
}
}
desc_listeners {
desc {
en: "Configuration for the dashboard listener."
zh: "仪表板监听器配置"
}
label {
en: "Listeners"
zh: "监听器"
}
}
desc_http {
desc {
en: "Configuration for the dashboard listener (plaintext)."
zh: "仪表板监听器(HTTP)配置"
}
label {
en: "HTTP"
zh: "HTTP"
}
}
desc_https {
desc {
en: "Configuration for the dashboard listener (TLS)."
zh: "仪表板监听器(HTTPS)配置"
}
label {
en: "HTTPS"
zh: "HTTPS"
}
}
listener_enable {
desc {
en: "Ignore or enable this listener"
zh: "忽略或启用该监听器配置"
}
label {
en: "Enable"
zh: "启用"
}
}
bind {
desc {
en: "Port without IP(18083) or port with specified IP(127.0.0.1:18083)."
zh: "监听的地址与端口在dashboard更新此配置时会重启dashboard服务。"
}
label {
en: "Bind"
zh: "绑定端口"
}
}
default_username {
desc {
en: "The default username of the automatically created dashboard user."
zh: "默认的仪表板用户名"
}
label {
en: "Default username"
zh: "默认用户名"
}
}
default_password {
desc {
en: """The initial default password for dashboard 'admin' user.
For safety, it should be changed as soon as possible."""
zh: """默认的仪表板用户密码
为了安全,应该尽快修改密码。"""
}
label {
en: "Default password"
zh: "默认密码"
}
}
cors {
desc {
en: """Support Cross-Origin Resource Sharing (CORS).
Allows a server to indicate any origins (domain, scheme, or port) other than
its own from which a browser should permit loading resources."""
zh: """支持跨域资源共享(CORS)
允许服务器指示任何来源(域名、协议或端口),除了本服务器之外的任何浏览器应允许加载资源。"""
}
label {
en: "CORS"
zh: "跨域资源共享"
}
}
i18n_lang {
desc {
en: "Internationalization language support."
zh: "swagger多语言支持"
}
label {
en: "I18n language"
zh: "多语言支持"
}
}
bootstrap_users_file {
desc {
en: "Initialize users file."
zh: "初始化用户文件"
}
label {
en: """Is used to add an administrative user to Dashboard when emqx is first launched,
the format is:
```
username1:password1
username2:password2
```
"""
zh: """用于在首次启动 emqx 时,为 Dashboard 添加管理用户,其格式为:
```
username1:password1
username2:password2
```
"""
}
}
}

View File

@ -48,7 +48,7 @@
api_secret_hash = <<>> :: binary() | '_', api_secret_hash = <<>> :: binary() | '_',
enable = true :: boolean() | '_', enable = true :: boolean() | '_',
desc = <<>> :: binary() | '_', desc = <<>> :: binary() | '_',
expired_at = 0 :: integer() | undefined | '_', expired_at = 0 :: integer() | undefined | infinity | '_',
created_at = 0 :: integer() | '_' created_at = 0 :: integer() | '_'
}). }).
@ -68,7 +68,7 @@ init_bootstrap_file() ->
init_bootstrap_file(File). init_bootstrap_file(File).
create(Name, Enable, ExpiredAt, Desc) -> create(Name, Enable, ExpiredAt, Desc) ->
case mnesia:table_info(?APP, size) < 1024 of case mnesia:table_info(?APP, size) < 100 of
true -> create_app(Name, Enable, ExpiredAt, Desc); true -> create_app(Name, Enable, ExpiredAt, Desc);
false -> {error, "Maximum ApiKey"} false -> {error, "Maximum ApiKey"}
end. end.
@ -237,16 +237,17 @@ init_bootstrap_file(File) ->
{ok, Dev} -> {ok, Dev} ->
{ok, MP} = re:compile(<<"(\.+):(\.+$)">>, [ungreedy]), {ok, MP} = re:compile(<<"(\.+):(\.+$)">>, [ungreedy]),
init_bootstrap_file(File, Dev, MP); init_bootstrap_file(File, Dev, MP);
{error, Reason} = Error -> {error, Reason0} ->
Reason = emqx_misc:explain_posix(Reason0),
?SLOG( ?SLOG(
error, error,
#{ #{
msg => "failed_to_open_the_bootstrap_file", msg => "failed_to_open_the_bootstrap_file",
file => File, file => File,
reason => emqx_misc:explain_posix(Reason) reason => Reason
} }
), ),
Error {error, Reason}
end. end.
init_bootstrap_file(File, Dev, MP) -> init_bootstrap_file(File, Dev, MP) ->

View File

@ -25,15 +25,62 @@ suite() -> [{timetrap, {minutes, 1}}].
groups() -> groups() ->
[ [
{parallel, [parallel], [t_create, t_update, t_delete, t_authorize, t_create_unexpired_app]}, {parallel, [parallel], [t_create, t_update, t_delete, t_authorize, t_create_unexpired_app]},
{sequence, [], [t_create_failed]} {sequence, [], [t_bootstrap_file, t_create_failed]}
]. ].
init_per_suite(Config) -> init_per_suite(Config) ->
emqx_mgmt_api_test_util:init_suite(), emqx_mgmt_api_test_util:init_suite([emqx_conf]),
Config. Config.
end_per_suite(_) -> end_per_suite(_) ->
emqx_mgmt_api_test_util:end_suite(). emqx_mgmt_api_test_util:end_suite([emqx_conf]).
t_bootstrap_file(_) ->
TestPath = <<"/api/v5/status">>,
Bin = <<"test-1:secret-1\ntest-2:secret-2">>,
File = "./bootstrap_api_keys.txt",
ok = file:write_file(File, Bin),
emqx:update_config([api_key, bootstrap_file], File),
ok = emqx_mgmt_auth:init_bootstrap_file(),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-1">>)),
%% relaunch to check if the table is changed.
Bin1 = <<"test-1:new-secret-1\ntest-2:new-secret-2">>,
ok = file:write_file(File, Bin1),
ok = emqx_mgmt_auth:init_bootstrap_file(),
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
%% Compatibility
Bin2 = <<"test-3:new-secret-3\ntest-4:new-secret-4">>,
ok = file:write_file(File, Bin2),
emqx:update_config([api_key, bootstrap_file], <<>>),
emqx:update_config([dashboard, bootstrap_users_file], File),
ok = emqx_mgmt_auth:init_bootstrap_file(),
?assertMatch(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
?assertMatch(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-3">>, <<"new-secret-3">>)),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-4">>, <<"new-secret-4">>)),
%% not found
NotFoundFile = "./bootstrap_apps_not_exist.txt",
emqx:update_config([api_key, bootstrap_file], NotFoundFile),
?assertMatch({error, "No such file or directory"}, emqx_mgmt_auth:init_bootstrap_file()),
%% bad format
BadBin = <<"test-1:secret-11\ntest-2 secret-12">>,
ok = file:write_file(File, BadBin),
emqx:update_config([api_key, bootstrap_file], File),
?assertMatch({error, #{reason := "invalid_format"}}, emqx_mgmt_auth:init_bootstrap_file()),
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-11">>)),
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-12">>)),
emqx:update_config([api_key, bootstrap_file], <<>>),
emqx:update_config([dashboard, bootstrap_users_file], <<>>),
ok.
t_create(_Config) -> t_create(_Config) ->
Name = <<"EMQX-API-KEY-1">>, Name = <<"EMQX-API-KEY-1">>,
@ -69,7 +116,7 @@ t_create_failed(_Config) ->
?assertEqual(BadRequest, create_app(LongName)), ?assertEqual(BadRequest, create_app(LongName)),
{ok, List} = list_app(), {ok, List} = list_app(),
CreateNum = 1024 - erlang:length(List), CreateNum = 100 - erlang:length(List),
Names = lists:map( Names = lists:map(
fun(Seq) -> fun(Seq) ->
<<"EMQX-API-FAILED-KEY-", (integer_to_binary(Seq))/binary>> <<"EMQX-API-FAILED-KEY-", (integer_to_binary(Seq))/binary>>