diff --git a/priv/emqx.schema b/priv/emqx.schema index f1d68d4e8..e2daf197f 100644 --- a/priv/emqx.schema +++ b/priv/emqx.schema @@ -2224,6 +2224,14 @@ end}. lists:flatten(OriginList) end end, + OCSPOpts = fun(Prefix) -> + Filter([ {ocsp_stapling_enabled, cuttlefish:conf_get(Prefix ++ ".enable_ocsp_stapling", Conf, undefined)} + , {ocsp_responder_url, cuttlefish:conf_get(Prefix ++ ".ocsp_responder_url", Conf, undefined)} + , {ocsp_issuer_pem, cuttlefish:conf_get(Prefix ++ ".ocsp_issuer_pem", Conf, undefined)} + , {ocsp_refresh_interval, cuttlefish:conf_get(Prefix ++ ".ocsp_refresh_interval", Conf, undefined)} + , {ocsp_refresh_http_timeout, cuttlefish:conf_get(Prefix ++ ".ocsp_refresh_http_timeout", Conf, undefined)} + ]) + end, LisOpts = fun(Prefix) -> Filter([{acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)}, @@ -2242,11 +2250,6 @@ end}. {supported_subprotocols, string:tokens(cuttlefish:conf_get(Prefix ++ ".supported_subprotocols", Conf, ""), ", ")}, {peer_cert_as_username, cuttlefish:conf_get(Prefix ++ ".peer_cert_as_username", Conf, undefined)}, {peer_cert_as_clientid, cuttlefish:conf_get(Prefix ++ ".peer_cert_as_clientid", Conf, undefined)}, - {ocsp_stapling_enabled, cuttlefish:conf_get(Prefix ++ ".enable_ocsp_stapling", Conf, undefined)}, - {ocsp_responder_url, cuttlefish:conf_get(Prefix ++ ".ocsp_responder_url", Conf, undefined)}, - {ocsp_issuer_pem, cuttlefish:conf_get(Prefix ++ ".ocsp_issuer_pem", Conf, undefined)}, - {ocsp_refresh_interval, cuttlefish:conf_get(Prefix ++ ".ocsp_refresh_interval", Conf, undefined)}, - {ocsp_refresh_http_timeout, cuttlefish:conf_get(Prefix ++ ".ocsp_refresh_http_timeout", Conf, undefined)}, {compress, cuttlefish:conf_get(Prefix ++ ".compress", Conf, undefined)}, {idle_timeout, cuttlefish:conf_get(Prefix ++ ".idle_timeout", Conf, undefined)}, {max_frame_size, cuttlefish:conf_get(Prefix ++ ".max_frame_size", Conf, undefined)}, @@ -2411,6 +2414,7 @@ end}. , {tcp_options, TcpOpts(Prefix)} , {ssl_options, SslOpts(Prefix)} , {crl_options, CRLOpts(Prefix)} + , {ocsp_options, OCSPOpts(Prefix)} | LisOpts(Prefix) ] } diff --git a/src/emqx_ocsp_cache.erl b/src/emqx_ocsp_cache.erl index 3f339e7e8..fb7766873 100644 --- a/src/emqx_ocsp_cache.erl +++ b/src/emqx_ocsp_cache.erl @@ -98,7 +98,8 @@ inject_sni_fun(Listener = #{proto := Proto, name := Name, opts := Options0}) -> %% because otherwise an anonymous function will end up in %% `app.*.config'... ListenerID = emqx_listeners:identifier(Listener), - case proplists:get_bool(ocsp_stapling_enabled, Options0) of + OCSPOpts = proplists:get_value(ocsp_options, Options0, []), + case proplists:get_bool(ocsp_stapling_enabled, OCSPOpts) of false -> Options0; true -> @@ -146,7 +147,8 @@ handle_call({http_fetch, ListenerID}, _From, State) -> handle_call({register_listener, ListenerID}, _From, State0) -> ?LOG(debug, "registering ocsp cache for ~p", [ListenerID]), #{opts := Opts} = emqx_listeners:find_by_id(ListenerID), - RefreshInterval0 = proplists:get_value(ocsp_refresh_interval, Opts), + OCSPOpts = proplists:get_value(ocsp_options, Opts), + RefreshInterval0 = proplists:get_value(ocsp_refresh_interval, OCSPOpts), RefreshInterval = max(RefreshInterval0, ?MIN_REFRESH_INTERVAL), State = State0#{{refresh_interval, ListenerID} => RefreshInterval}, {reply, ok, ensure_timer(ListenerID, State, 0)}; @@ -181,8 +183,9 @@ code_change(_Vsn, State, _Extra) -> ListenersToPatch = lists:filter( fun(#{opts := Opts}) -> - undefined =/= proplists:get_value(ocsp_responder_url, Opts) andalso - false =/= proplists:get_bool(ocsp_stapling_enabled, Opts) + OCSPOpts = proplists:get_value(ocsp_options, Opts), + undefined =/= proplists:get_value(ocsp_responder_url, OCSPOpts, undefined) andalso + false =/= proplists:get_bool(ocsp_stapling_enabled, OCSPOpts) end, emqx:get_env(listeners, [])), PatchedListeners = [L#{opts => ?MODULE:inject_sni_fun(L)} || L <- ListenersToPatch], @@ -229,9 +232,10 @@ read_server_cert(ServerCertPemPath0) -> do_http_fetch_and_cache(ListenerID) -> #{opts := Options} = emqx_listeners:find_by_id(ListenerID), - ResponderURL0 = proplists:get_value(ocsp_responder_url, Options, undefined), + OCSPOpts = proplists:get_value(ocsp_options, Options), + ResponderURL0 = proplists:get_value(ocsp_responder_url, OCSPOpts, undefined), ResponderURL = uri_string:normalize(ResponderURL0), - IssuerPemPath = proplists:get_value(ocsp_issuer_pem, Options, undefined), + IssuerPemPath = proplists:get_value(ocsp_issuer_pem, OCSPOpts, undefined), SSLOpts = proplists:get_value(ssl_options, Options, undefined), ServerCertPemPath = proplists:get_value(certfile, SSLOpts, undefined), IssuerPem = case file:read_file(IssuerPemPath) of @@ -240,7 +244,7 @@ do_http_fetch_and_cache(ListenerID) -> end, ServerCert = read_server_cert(ServerCertPemPath), Request = build_ocsp_request(IssuerPem, ServerCert), - HTTPTimeout = proplists:get_value(ocsp_refresh_http_timeout, Options), + HTTPTimeout = proplists:get_value(ocsp_refresh_http_timeout, OCSPOpts), ?tp(ocsp_http_fetch, #{ listener_id => ListenerID , responder_url => ResponderURL , timeout => HTTPTimeout diff --git a/test/emqx_ocsp_cache_SUITE.erl b/test/emqx_ocsp_cache_SUITE.erl index f85945fca..587125fc5 100644 --- a/test/emqx_ocsp_cache_SUITE.erl +++ b/test/emqx_ocsp_cache_SUITE.erl @@ -96,9 +96,11 @@ init_per_testcase(t_openssl_client, Config) -> , {cacertfile, CACert} ]), Opts1 = proplists:delete(ssl_options, Opts0), - Opts2 = emqx_misc:merge_opts(Opts1, [ {ocsp_stapling_enabled, true} - , {ocsp_responder_url, "http://127.0.0.1:9877"} - , {ocsp_issuer_pem, IssuerPem} + OCSPOpts = [ {ocsp_stapling_enabled, true} + , {ocsp_responder_url, "http://127.0.0.1:9877"} + , {ocsp_issuer_pem, IssuerPem} + ], + Opts2 = emqx_misc:merge_opts(Opts1, [ {ocsp_options, OCSPOpts} , {ssl_options, SSLOpts2}]), Listeners = [ SSLListener0#{opts => Opts2} | Listeners1], @@ -139,18 +141,20 @@ init_per_testcase(_TestCase, Config) -> end), {ok, CachePid} = emqx_ocsp_cache:start_link(), DataDir = ?config(data_dir, Config), + OCSPOpts = [ {ocsp_stapling_enabled, true} + , {ocsp_responder_url, "http://localhost:9877"} + , {ocsp_issuer_pem, + filename:join(DataDir, "ocsp-issuer.pem")} + , {ocsp_refresh_http_timeout, 15_000} + , {ocsp_refresh_interval, 1_000} + ], application:set_env( emqx, listeners, [#{ proto => ssl , name => "test_ocsp" , opts => [ {ssl_options, [{certfile, filename:join(DataDir, "server.pem")}]} - , {ocsp_stapling_enabled, true} - , {ocsp_responder_url, "http://localhost:9877"} - , {ocsp_issuer_pem, - filename:join(DataDir, "ocsp-issuer.pem")} - , {ocsp_refresh_http_timeout, 15_000} - , {ocsp_refresh_interval, 1_000} + , {ocsp_options, OCSPOpts} ] }]), snabbkaffe:start_trace(),