|
|
@@ -85,6 +85,13 @@
|
|
|
reset_proxy/2
|
|
|
]).
|
|
|
|
|
|
+%% TLS certs API
|
|
|
+-export([
|
|
|
+ gen_ca/2,
|
|
|
+ gen_host_cert/3,
|
|
|
+ gen_host_cert/4
|
|
|
+]).
|
|
|
+
|
|
|
-define(CERTS_PATH(CertName), filename:join(["etc", "certs", CertName])).
|
|
|
|
|
|
-define(MQTT_SSL_CLIENT_CERTS, [
|
|
|
@@ -562,6 +569,7 @@ ensure_quic_listener(Name, UdpPort, ExtraSettings) ->
|
|
|
mountpoint => <<>>,
|
|
|
zone => default
|
|
|
},
|
|
|
+
|
|
|
Conf2 = maps:merge(Conf, ExtraSettings),
|
|
|
emqx_config:put([listeners, quic, Name], Conf2),
|
|
|
case emqx_listeners:start_listener(emqx_listeners:listener_id(quic, Name)) of
|
|
|
@@ -1075,6 +1083,104 @@ latency_up_proxy(off, Name, ProxyHost, ProxyPort) ->
|
|
|
).
|
|
|
|
|
|
%%-------------------------------------------------------------------------------
|
|
|
+%% TLS certs
|
|
|
+%%-------------------------------------------------------------------------------
|
|
|
+gen_ca(Path, Name) ->
|
|
|
+ %% Generate ca.pem and ca.key which will be used to generate certs
|
|
|
+ %% for hosts server and clients
|
|
|
+ ECKeyFile = filename(Path, "~s-ec.key", [Name]),
|
|
|
+ filelib:ensure_dir(ECKeyFile),
|
|
|
+ os:cmd("openssl ecparam -name secp256r1 > " ++ ECKeyFile),
|
|
|
+ Cmd = lists:flatten(
|
|
|
+ io_lib:format(
|
|
|
+ "openssl req -new -x509 -nodes "
|
|
|
+ "-newkey ec:~s "
|
|
|
+ "-keyout ~s -out ~s -days 3650 "
|
|
|
+ "-subj \"/C=SE/O=Internet Widgits Pty Ltd CA\"",
|
|
|
+ [
|
|
|
+ ECKeyFile,
|
|
|
+ ca_key_name(Path, Name),
|
|
|
+ ca_cert_name(Path, Name)
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ os:cmd(Cmd).
|
|
|
+
|
|
|
+ca_cert_name(Path, Name) ->
|
|
|
+ filename(Path, "~s.pem", [Name]).
|
|
|
+ca_key_name(Path, Name) ->
|
|
|
+ filename(Path, "~s.key", [Name]).
|
|
|
+
|
|
|
+gen_host_cert(H, CaName, Path) ->
|
|
|
+ gen_host_cert(H, CaName, Path, #{}).
|
|
|
+
|
|
|
+gen_host_cert(H, CaName, Path, Opts) ->
|
|
|
+ ECKeyFile = filename(Path, "~s-ec.key", [CaName]),
|
|
|
+ CN = str(H),
|
|
|
+ HKey = filename(Path, "~s.key", [H]),
|
|
|
+ HCSR = filename(Path, "~s.csr", [H]),
|
|
|
+ HPEM = filename(Path, "~s.pem", [H]),
|
|
|
+ HEXT = filename(Path, "~s.extfile", [H]),
|
|
|
+ PasswordArg =
|
|
|
+ case maps:get(password, Opts, undefined) of
|
|
|
+ undefined ->
|
|
|
+ " -nodes ";
|
|
|
+ Password ->
|
|
|
+ io_lib:format(" -passout pass:'~s' ", [Password])
|
|
|
+ end,
|
|
|
+ CSR_Cmd =
|
|
|
+ lists:flatten(
|
|
|
+ io_lib:format(
|
|
|
+ "openssl req -new ~s -newkey ec:~s "
|
|
|
+ "-keyout ~s -out ~s "
|
|
|
+ "-addext \"subjectAltName=DNS:~s\" "
|
|
|
+ "-addext keyUsage=digitalSignature,keyAgreement "
|
|
|
+ "-subj \"/C=SE/O=Internet Widgits Pty Ltd/CN=~s\"",
|
|
|
+ [PasswordArg, ECKeyFile, HKey, HCSR, CN, CN]
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ create_file(
|
|
|
+ HEXT,
|
|
|
+ "keyUsage=digitalSignature,keyAgreement\n"
|
|
|
+ "subjectAltName=DNS:~s\n",
|
|
|
+ [CN]
|
|
|
+ ),
|
|
|
+ CERT_Cmd =
|
|
|
+ lists:flatten(
|
|
|
+ io_lib:format(
|
|
|
+ "openssl x509 -req "
|
|
|
+ "-extfile ~s "
|
|
|
+ "-in ~s -CA ~s -CAkey ~s -CAcreateserial "
|
|
|
+ "-out ~s -days 500",
|
|
|
+ [
|
|
|
+ HEXT,
|
|
|
+ HCSR,
|
|
|
+ ca_cert_name(Path, CaName),
|
|
|
+ ca_key_name(Path, CaName),
|
|
|
+ HPEM
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ ct:pal(os:cmd(CSR_Cmd)),
|
|
|
+ ct:pal(os:cmd(CERT_Cmd)),
|
|
|
+ file:delete(HEXT).
|
|
|
+
|
|
|
+filename(Path, F, A) ->
|
|
|
+ filename:join(Path, str(io_lib:format(F, A))).
|
|
|
+
|
|
|
+str(Arg) ->
|
|
|
+ binary_to_list(iolist_to_binary(Arg)).
|
|
|
+
|
|
|
+create_file(Filename, Fmt, Args) ->
|
|
|
+ filelib:ensure_dir(Filename),
|
|
|
+ {ok, F} = file:open(Filename, [write]),
|
|
|
+ try
|
|
|
+ io:format(F, Fmt, Args)
|
|
|
+ after
|
|
|
+ file:close(F)
|
|
|
+ end,
|
|
|
+ ok.
|
|
|
+%%-------------------------------------------------------------------------------
|
|
|
%% Testcase teardown utilities
|
|
|
%%-------------------------------------------------------------------------------
|
|
|
|