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