fix(psk): reformat codes
This commit is contained in:
parent
a156933841
commit
c1ba15f8f0
|
@ -1,21 +1,29 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
|
|
||||||
{deps, [ {emqx, {path, "../emqx"}}
|
{deps, [{emqx, {path, "../emqx"}}]}.
|
||||||
]}.
|
|
||||||
|
|
||||||
{edoc_opts, [{preprocess, true}]}.
|
{edoc_opts, [{preprocess, true}]}.
|
||||||
{erl_opts, [warn_unused_vars,
|
{erl_opts, [
|
||||||
|
warn_unused_vars,
|
||||||
warn_shadow_vars,
|
warn_shadow_vars,
|
||||||
warnings_as_errors,
|
warnings_as_errors,
|
||||||
warn_unused_import,
|
warn_unused_import,
|
||||||
warn_obsolete_guard,
|
warn_obsolete_guard,
|
||||||
debug_info,
|
debug_info,
|
||||||
{parse_transform}]}.
|
{parse_transform}
|
||||||
|
]}.
|
||||||
|
|
||||||
{xref_checks, [undefined_function_calls, undefined_functions,
|
{xref_checks, [
|
||||||
locals_not_used, deprecated_function_calls,
|
undefined_function_calls,
|
||||||
warnings_as_errors, deprecated_functions]}.
|
undefined_functions,
|
||||||
|
locals_not_used,
|
||||||
|
deprecated_function_calls,
|
||||||
|
warnings_as_errors,
|
||||||
|
deprecated_functions
|
||||||
|
]}.
|
||||||
|
|
||||||
{cover_enabled, true}.
|
{cover_enabled, true}.
|
||||||
{cover_opts, [verbose]}.
|
{cover_opts, [verbose]}.
|
||||||
{cover_export_enabled, true}.
|
{cover_export_enabled, true}.
|
||||||
|
|
||||||
|
{project_plugins, [erlfmt]}.
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
{application, emqx_psk,
|
{application, emqx_psk, [
|
||||||
[{description, "EMQX PSK"},
|
{description, "EMQX PSK"},
|
||||||
{vsn, "5.0.0"}, % strict semver, bump manually!
|
% strict semver, bump manually!
|
||||||
|
{vsn, "5.0.0"},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_psk_sup]},
|
{registered, [emqx_psk_sup]},
|
||||||
{applications, [kernel,stdlib]},
|
{applications, [kernel, stdlib]},
|
||||||
{mod, {emqx_psk_app,[]}},
|
{mod, {emqx_psk_app, []}},
|
||||||
{env, []},
|
{env, []},
|
||||||
{licenses, ["Apache-2.0"]},
|
{licenses, ["Apache-2.0"]},
|
||||||
{maintainers, ["EMQX Team <contact@emqx.io>"]},
|
{maintainers, ["EMQX Team <contact@emqx.io>"]},
|
||||||
{links, [{"Homepage", "https://emqx.io/"},
|
{links, [
|
||||||
|
{"Homepage", "https://emqx.io/"},
|
||||||
{"Github", "https://github.com/emqx/emqx"}
|
{"Github", "https://github.com/emqx/emqx"}
|
||||||
]}
|
]}
|
||||||
]}.
|
]}.
|
||||||
|
|
|
@ -20,29 +20,33 @@
|
||||||
|
|
||||||
-include_lib("emqx/include/logger.hrl").
|
-include_lib("emqx/include/logger.hrl").
|
||||||
|
|
||||||
-export([ load/0
|
-export([
|
||||||
, unload/0
|
load/0,
|
||||||
, on_psk_lookup/2
|
unload/0,
|
||||||
, import/1
|
on_psk_lookup/2,
|
||||||
]).
|
import/1
|
||||||
|
]).
|
||||||
|
|
||||||
-export([ start_link/0
|
-export([
|
||||||
, stop/0
|
start_link/0,
|
||||||
]).
|
stop/0
|
||||||
|
]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([ init/1
|
-export([
|
||||||
, handle_call/3
|
init/1,
|
||||||
, handle_cast/2
|
handle_call/3,
|
||||||
, handle_info/2
|
handle_cast/2,
|
||||||
, terminate/2
|
handle_info/2,
|
||||||
, code_change/3
|
terminate/2,
|
||||||
]).
|
code_change/3
|
||||||
|
]).
|
||||||
|
|
||||||
-record(psk_entry, {psk_id :: binary(),
|
-record(psk_entry, {
|
||||||
|
psk_id :: binary(),
|
||||||
shared_secret :: binary(),
|
shared_secret :: binary(),
|
||||||
extra :: term()
|
extra :: term()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-export([mnesia/1]).
|
-export([mnesia/1]).
|
||||||
|
|
||||||
|
@ -65,7 +69,7 @@
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
%% @doc Create or replicate tables.
|
%% @doc Create or replicate tables.
|
||||||
-spec(mnesia(boot | copy) -> ok).
|
-spec mnesia(boot | copy) -> ok.
|
||||||
mnesia(boot) ->
|
mnesia(boot) ->
|
||||||
ok = mria:create_table(?TAB, [
|
ok = mria:create_table(?TAB, [
|
||||||
{rlog_shard, ?PSK_SHARD},
|
{rlog_shard, ?PSK_SHARD},
|
||||||
|
@ -73,7 +77,8 @@ mnesia(boot) ->
|
||||||
{storage, disc_copies},
|
{storage, disc_copies},
|
||||||
{record_name, psk_entry},
|
{record_name, psk_entry},
|
||||||
{attributes, record_info(fields, psk_entry)},
|
{attributes, record_info(fields, psk_entry)},
|
||||||
{storage_properties, [{ets, [{read_concurrency, true}]}]}]).
|
{storage_properties, [{ets, [{read_concurrency, true}]}]}
|
||||||
|
]).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% APIs
|
%% APIs
|
||||||
|
@ -109,11 +114,13 @@ stop() ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
init(_Opts) ->
|
init(_Opts) ->
|
||||||
_ = case get_config(enable) of
|
_ =
|
||||||
|
case get_config(enable) of
|
||||||
true -> load();
|
true -> load();
|
||||||
false -> ?SLOG(info, #{msg => "emqx_psk_disabled"})
|
false -> ?SLOG(info, #{msg => "emqx_psk_disabled"})
|
||||||
end,
|
end,
|
||||||
_ = case get_config(init_file) of
|
_ =
|
||||||
|
case get_config(init_file) of
|
||||||
undefined -> ok;
|
undefined -> ok;
|
||||||
InitFile -> import_psks(InitFile)
|
InitFile -> import_psks(InitFile)
|
||||||
end,
|
end,
|
||||||
|
@ -121,7 +128,6 @@ init(_Opts) ->
|
||||||
|
|
||||||
handle_call({import, SrcFile}, _From, State) ->
|
handle_call({import, SrcFile}, _From, State) ->
|
||||||
{reply, import_psks(SrcFile), State};
|
{reply, import_psks(SrcFile), State};
|
||||||
|
|
||||||
handle_call(Req, _From, State) ->
|
handle_call(Req, _From, State) ->
|
||||||
?SLOG(info, #{msg => "unexpected_call_discarded", req => Req}),
|
?SLOG(info, #{msg => "unexpected_call_discarded", req => Req}),
|
||||||
{reply, {error, unexpected}, State}.
|
{reply, {error, unexpected}, State}.
|
||||||
|
@ -157,25 +163,32 @@ get_config(chunk_size) ->
|
||||||
import_psks(SrcFile) ->
|
import_psks(SrcFile) ->
|
||||||
case file:open(SrcFile, [read, raw, binary, read_ahead]) of
|
case file:open(SrcFile, [read, raw, binary, read_ahead]) of
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?SLOG(error, #{msg => "failed_to_open_psk_file",
|
?SLOG(error, #{
|
||||||
|
msg => "failed_to_open_psk_file",
|
||||||
file => SrcFile,
|
file => SrcFile,
|
||||||
reason => Reason}),
|
reason => Reason
|
||||||
|
}),
|
||||||
{error, Reason};
|
{error, Reason};
|
||||||
{ok, Io} ->
|
{ok, Io} ->
|
||||||
try import_psks(Io, get_config(separator), get_config(chunk_size), 0) of
|
try import_psks(Io, get_config(separator), get_config(chunk_size), 0) of
|
||||||
ok -> ok;
|
ok ->
|
||||||
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?SLOG(error, #{msg => "failed_to_import_psk_file",
|
?SLOG(error, #{
|
||||||
|
msg => "failed_to_import_psk_file",
|
||||||
file => SrcFile,
|
file => SrcFile,
|
||||||
reason => Reason}),
|
reason => Reason
|
||||||
|
}),
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
catch
|
catch
|
||||||
Exception:Reason:Stacktrace ->
|
Exception:Reason:Stacktrace ->
|
||||||
?SLOG(error, #{msg => "failed_to_import_psk_file",
|
?SLOG(error, #{
|
||||||
|
msg => "failed_to_import_psk_file",
|
||||||
file => SrcFile,
|
file => SrcFile,
|
||||||
exception => Exception,
|
exception => Exception,
|
||||||
reason => Reason,
|
reason => Reason,
|
||||||
stacktrace => Stacktrace}),
|
stacktrace => Stacktrace
|
||||||
|
}),
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
after
|
after
|
||||||
_ = file:close(Io)
|
_ = file:close(Io)
|
||||||
|
@ -218,9 +231,12 @@ get_psks(Io, Delimiter, Remaining, Acc) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
insert_psks(Entries) ->
|
insert_psks(Entries) ->
|
||||||
lists:foreach(fun(Entry) ->
|
lists:foreach(
|
||||||
|
fun(Entry) ->
|
||||||
insert_psk(Entry)
|
insert_psk(Entry)
|
||||||
end, Entries).
|
end,
|
||||||
|
Entries
|
||||||
|
).
|
||||||
|
|
||||||
insert_psk({PSKIdentity, SharedSecret}) ->
|
insert_psk({PSKIdentity, SharedSecret}) ->
|
||||||
mnesia:write(?TAB, #psk_entry{psk_id = PSKIdentity, shared_secret = SharedSecret}, write).
|
mnesia:write(?TAB, #psk_entry{psk_id = PSKIdentity, shared_secret = SharedSecret}, write).
|
||||||
|
@ -233,7 +249,8 @@ trim_crlf(Bin) ->
|
||||||
?CR -> binary:part(Bin, 0, Size - 2);
|
?CR -> binary:part(Bin, 0, Size - 2);
|
||||||
_ -> binary:part(Bin, 0, Size - 1)
|
_ -> binary:part(Bin, 0, Size - 1)
|
||||||
end;
|
end;
|
||||||
_ -> Bin
|
_ ->
|
||||||
|
Bin
|
||||||
end.
|
end.
|
||||||
|
|
||||||
trans(Fun, Args) ->
|
trans(Fun, Args) ->
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
|
|
||||||
-behaviour(application).
|
-behaviour(application).
|
||||||
|
|
||||||
-export([ start/2
|
-export([
|
||||||
, stop/1
|
start/2,
|
||||||
]).
|
stop/1
|
||||||
|
]).
|
||||||
|
|
||||||
start(_Type, _Args) ->
|
start(_Type, _Args) ->
|
||||||
{ok, Sup} = emqx_psk_sup:start_link(),
|
{ok, Sup} = emqx_psk_sup:start_link(),
|
||||||
|
|
|
@ -20,51 +20,74 @@
|
||||||
|
|
||||||
-include_lib("typerefl/include/types.hrl").
|
-include_lib("typerefl/include/types.hrl").
|
||||||
|
|
||||||
-export([ roots/0
|
-export([
|
||||||
, fields/1
|
roots/0,
|
||||||
]).
|
fields/1
|
||||||
|
]).
|
||||||
|
|
||||||
-import(emqx_schema, [sc/2]).
|
-import(emqx_schema, [sc/2]).
|
||||||
|
|
||||||
roots() -> ["psk_authentication"].
|
roots() -> ["psk_authentication"].
|
||||||
|
|
||||||
fields("psk_authentication") ->
|
fields("psk_authentication") ->
|
||||||
#{fields => fields(),
|
#{
|
||||||
desc => """PSK stands for 'Pre-Shared Keys'.
|
fields => fields(),
|
||||||
This config to enable TLS-PSK authentication.
|
desc =>
|
||||||
|
""
|
||||||
<strong>Important!</strong> Make sure the SSL listener with
|
"PSK stands for 'Pre-Shared Keys'.\n"
|
||||||
only <code>tlsv1.2</code> enabled, and also PSK cipher suites
|
"This config to enable TLS-PSK authentication.\n"
|
||||||
configured, such as <code>RSA-PSK-AES256-GCM-SHA384</code>.
|
"\n"
|
||||||
See listener SSL options config for more details.
|
"<strong>Important!</strong> Make sure the SSL listener with\n"
|
||||||
|
"only <code>tlsv1.2</code> enabled, and also PSK cipher suites\n"
|
||||||
The IDs and secrets can be provided from a file the path
|
"configured, such as <code>RSA-PSK-AES256-GCM-SHA384</code>.\n"
|
||||||
to which is configurable by the <code>init_file</code> field.
|
"See listener SSL options config for more details.\n"
|
||||||
"""
|
"\n"
|
||||||
|
"The IDs and secrets can be provided from a file the path\n"
|
||||||
|
"to which is configurable by the <code>init_file</code> field.\n"
|
||||||
|
""
|
||||||
}.
|
}.
|
||||||
|
|
||||||
fields() ->
|
fields() ->
|
||||||
[ {enable, sc(boolean(), #{default => false,
|
[
|
||||||
|
{enable,
|
||||||
|
sc(boolean(), #{
|
||||||
|
default => false,
|
||||||
desc => <<"Whether to enable TLS PSK support">>
|
desc => <<"Whether to enable TLS PSK support">>
|
||||||
})}
|
})},
|
||||||
, {init_file, sc(binary(),
|
{init_file,
|
||||||
#{required => false,
|
sc(
|
||||||
|
binary(),
|
||||||
|
#{
|
||||||
|
required => false,
|
||||||
desc =>
|
desc =>
|
||||||
<<"If init_file is specified, emqx will import PSKs from the file ",
|
<<"If init_file is specified, emqx will import PSKs from the file ",
|
||||||
"into the built-in database at startup for use by the runtime. ",
|
"into the built-in database at startup for use by the runtime. ",
|
||||||
"The file has to be structured line-by-line, each line must be in ",
|
"The file has to be structured line-by-line, each line must be in ",
|
||||||
"the format of <code>PSKIdentity:SharedSecret</code>. For example: ",
|
"the format of <code>PSKIdentity:SharedSecret</code>. For example: ",
|
||||||
"<code>mydevice1:c2VjcmV0</code>">>
|
"<code>mydevice1:c2VjcmV0</code>">>
|
||||||
})}
|
}
|
||||||
, {separator, sc(binary(),
|
)},
|
||||||
#{default => <<":">>,
|
{separator,
|
||||||
|
sc(
|
||||||
|
binary(),
|
||||||
|
#{
|
||||||
|
default => <<":">>,
|
||||||
desc =>
|
desc =>
|
||||||
<<"The separator between <code>PSKIdentity</code>"
|
<<
|
||||||
" and <code>SharedSecret</code> in the psk file">>
|
"The separator between <code>PSKIdentity</code>"
|
||||||
})}
|
" and <code>SharedSecret</code> in the psk file"
|
||||||
, {chunk_size, sc(integer(),
|
>>
|
||||||
#{default => 50,
|
}
|
||||||
desc => <<"The size of each chunk used to import to"
|
)},
|
||||||
" the built-in database from psk file">>
|
{chunk_size,
|
||||||
})}
|
sc(
|
||||||
|
integer(),
|
||||||
|
#{
|
||||||
|
default => 50,
|
||||||
|
desc => <<
|
||||||
|
"The size of each chunk used to import to"
|
||||||
|
" the built-in database from psk file"
|
||||||
|
>>
|
||||||
|
}
|
||||||
|
)}
|
||||||
].
|
].
|
||||||
|
|
|
@ -26,10 +26,14 @@ start_link() ->
|
||||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
{ok, {{one_for_one, 10, 3600},
|
{ok,
|
||||||
[#{id => emqx_psk,
|
{{one_for_one, 10, 3600}, [
|
||||||
|
#{
|
||||||
|
id => emqx_psk,
|
||||||
start => {emqx_psk, start_link, []},
|
start => {emqx_psk, start_link, []},
|
||||||
restart => permanent,
|
restart => permanent,
|
||||||
shutdown => 5000,
|
shutdown => 5000,
|
||||||
type => worker,
|
type => worker,
|
||||||
modules => [emqx_psk]}]}}.
|
modules => [emqx_psk]
|
||||||
|
}
|
||||||
|
]}}.
|
||||||
|
|
|
@ -29,15 +29,21 @@ all() ->
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
meck:new(emqx_config, [non_strict, passthrough, no_history, no_link]),
|
meck:new(emqx_config, [non_strict, passthrough, no_history, no_link]),
|
||||||
meck:expect(emqx_config, get, fun([psk_authentication, enable]) -> true;
|
meck:expect(emqx_config, get, fun
|
||||||
|
([psk_authentication, enable]) -> true;
|
||||||
([psk_authentication, chunk_size]) -> 50;
|
([psk_authentication, chunk_size]) -> 50;
|
||||||
(KeyPath) -> meck:passthrough([KeyPath])
|
(KeyPath) -> meck:passthrough([KeyPath])
|
||||||
end),
|
end),
|
||||||
meck:expect(emqx_config, get, fun([psk_authentication, init_file], _) ->
|
meck:expect(emqx_config, get, fun
|
||||||
filename:join([code:lib_dir(emqx_psk, test),
|
([psk_authentication, init_file], _) ->
|
||||||
"data/init.psk"]);
|
filename:join([
|
||||||
([psk_authentication, separator], _) -> <<":">>;
|
code:lib_dir(emqx_psk, test),
|
||||||
(KeyPath, Default) -> meck:passthrough([KeyPath, Default])
|
"data/init.psk"
|
||||||
|
]);
|
||||||
|
([psk_authentication, separator], _) ->
|
||||||
|
<<":">>;
|
||||||
|
(KeyPath, Default) ->
|
||||||
|
meck:passthrough([KeyPath, Default])
|
||||||
end),
|
end),
|
||||||
emqx_common_test_helpers:start_apps([emqx_psk]),
|
emqx_common_test_helpers:start_apps([emqx_psk]),
|
||||||
Config.
|
Config.
|
||||||
|
@ -48,7 +54,6 @@ end_per_suite(_) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_psk_lookup(_) ->
|
t_psk_lookup(_) ->
|
||||||
|
|
||||||
PSKIdentity1 = <<"myclient1">>,
|
PSKIdentity1 = <<"myclient1">>,
|
||||||
SharedSecret1 = <<"8c701116e9127c57a99d5563709af3deaca75563e2c4dd0865701ae839fb6d79">>,
|
SharedSecret1 = <<"8c701116e9127c57a99d5563709af3deaca75563e2c4dd0865701ae839fb6d79">>,
|
||||||
?assertEqual({stop, {ok, SharedSecret1}}, emqx_psk:on_psk_lookup(PSKIdentity1, any)),
|
?assertEqual({stop, {ok, SharedSecret1}}, emqx_psk:on_psk_lookup(PSKIdentity1, any)),
|
||||||
|
@ -59,24 +64,27 @@ t_psk_lookup(_) ->
|
||||||
|
|
||||||
?assertEqual(ignore, emqx_psk:on_psk_lookup(<<"myclient3">>, any)),
|
?assertEqual(ignore, emqx_psk:on_psk_lookup(<<"myclient3">>, any)),
|
||||||
|
|
||||||
ClientLookup = fun(psk, undefined, _) -> {ok, SharedSecret1};
|
ClientLookup = fun
|
||||||
|
(psk, undefined, _) -> {ok, SharedSecret1};
|
||||||
(psk, _, _) -> error
|
(psk, _, _) -> error
|
||||||
end,
|
end,
|
||||||
|
|
||||||
ClientTLSOpts = #{ versions => ['tlsv1.2']
|
ClientTLSOpts = #{
|
||||||
, ciphers => ["PSK-AES256-CBC-SHA"]
|
versions => ['tlsv1.2'],
|
||||||
, psk_identity => "myclient1"
|
ciphers => ["PSK-AES256-CBC-SHA"],
|
||||||
, verify => verify_none
|
psk_identity => "myclient1",
|
||||||
, user_lookup_fun => {ClientLookup, undefined}
|
verify => verify_none,
|
||||||
|
user_lookup_fun => {ClientLookup, undefined}
|
||||||
},
|
},
|
||||||
|
|
||||||
ServerTLSOpts = #{ versions => ['tlsv1.2']
|
ServerTLSOpts = #{
|
||||||
, ciphers => ["PSK-AES256-CBC-SHA"]
|
versions => ['tlsv1.2'],
|
||||||
, verify => verify_none
|
ciphers => ["PSK-AES256-CBC-SHA"],
|
||||||
, reuseaddr => true
|
verify => verify_none,
|
||||||
, user_lookup_fun => {fun emqx_tls_psk:lookup/3, undefined}
|
reuseaddr => true,
|
||||||
|
user_lookup_fun => {fun emqx_tls_psk:lookup/3, undefined}
|
||||||
},
|
},
|
||||||
emqx_config:put([listeners, ssl ,default, ssl], ServerTLSOpts),
|
emqx_config:put([listeners, ssl, default, ssl], ServerTLSOpts),
|
||||||
emqx_listeners:restart_listener('ssl:default'),
|
emqx_listeners:restart_listener('ssl:default'),
|
||||||
|
|
||||||
{ok, Socket} = ssl:connect("127.0.0.1", 8883, maps:to_list(ClientTLSOpts)),
|
{ok, Socket} = ssl:connect("127.0.0.1", 8883, maps:to_list(ClientTLSOpts)),
|
||||||
|
|
|
@ -14,6 +14,7 @@ APPS+=( 'lib-ee/emqx_enterprise_conf' 'lib-ee/emqx_license' )
|
||||||
APPS+=( 'apps/emqx_exhook')
|
APPS+=( 'apps/emqx_exhook')
|
||||||
APPS+=( 'apps/emqx_retainer' 'apps/emqx_slow_subs')
|
APPS+=( 'apps/emqx_retainer' 'apps/emqx_slow_subs')
|
||||||
APPS+=( 'apps/emqx_management')
|
APPS+=( 'apps/emqx_management')
|
||||||
|
APPS+=( 'apps/emqx_psk')
|
||||||
|
|
||||||
for app in "${APPS[@]}"; do
|
for app in "${APPS[@]}"; do
|
||||||
echo "$app ..."
|
echo "$app ..."
|
||||||
|
|
Loading…
Reference in New Issue