Skip to content

Commit d326639

Browse files
committed
Add separate monitor for epp_tls_acceptor reloading
1 parent d0a9be7 commit d326639

File tree

7 files changed

+99
-41
lines changed

7 files changed

+99
-41
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ of Erlang property list.
118118
| `cacertfile_path` | `/opt/ca/ca.crt.pem` | SSLCACertificateFile | Where is the client root CA located. Can be inside apps/epp_proxy/priv or absolute path.
119119
| `certfile_path` | `/opt/ca/server.crt.pem` | SSLCertificateFile | Where is the server certificate located. Can be inside apps/epp_proxy/priv or absolute path.
120120
| `keyfile_path` | `/opt/ca/server.key.pem` | SSLCertificateKeyFile | Where is the server key located. Can be inside apps/epp_proxy/priv or absolute path.
121-
| `crlfile_path` | `/opt/ca/crl.pem` | SSLCARevocationFile | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path. When not set, not CRL check is performed.
121+
| `crlfile_path` | `/opt/ca/crl` | SSLCARevocationFile | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path. When not set, not CRL check is performed. CLRs in this directory must be rehashed by `c_rehash` command as per this solution (https://stackoverflow.com/posts/51480191/revisions)
122+
122123

123124

124125
Migrating from mod_epp

apps/epp_proxy/src/epp_proxy_sup.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ init([]) ->
6060
MemoryMonitor = #{id => memory_monitor, type => worker,
6161
modules => [memory_monitor],
6262
start => {memory_monitor, start_link, []}},
63+
TLSMonitor = #{id => epp_tls_monitor, type => worker,
64+
modules => [epp_tls_monitor],
65+
start => {epp_tls_monitor, start_link, []}},
6366
SharedSpecs = [TLSAcceptor, PoolSupervisor,
64-
MemoryMonitor],
67+
MemoryMonitor, TLSMonitor],
6568
ChildrenSpec = case ?DevMode of
6669
{ok, true} -> [TCPAcceptor | SharedSpecs];
6770
_ -> SharedSpecs

apps/epp_proxy/src/epp_tls_acceptor.erl

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212

1313
%% gen_server callbacks
1414
-export([handle_call/3, handle_cast/2, init/1,
15-
start_link/1, terminate/2, handle_info/1, handle_info/2]).
15+
start_link/1, terminate/2]).
1616

1717
-export([crl_file/0, crl_file/1]).
1818

19-
-record(state, {socket, port, options, timer}).
19+
-record(state, {socket, port, options}).
2020

2121
start_link(Port) ->
2222
gen_server:start_link({local, ?SERVER}, ?MODULE, Port,
@@ -29,12 +29,11 @@ init(Port) ->
2929
{cacertfile, ca_cert_file()}, {certfile, cert_file()},
3030
{keyfile, key_file()}],
3131
Options = handle_crl_check_options(DefaultOptions),
32-
TimerReference = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), reload_clr_file),
3332
{ok, ListenSocket} = ssl:listen(Port, Options),
3433
gen_server:cast(self(), accept),
3534
{ok,
3635
#state{socket = ListenSocket, port = Port,
37-
options = Options, timer = TimerReference}}.
36+
options = Options}}.
3837

3938
%% Acceptor has only one state that goes in a loop:
4039
%% 1. Listen for a connection from anyone.
@@ -55,35 +54,7 @@ handle_cast(accept,
5554
State#state{socket = ListenSocket, port = Port,
5655
options = Options}}.
5756

58-
handle_info(reload_crl_file) ->
59-
case crl_file() of
60-
undefined -> {noreply};
61-
{ok, File} ->
62-
ssl_crl_cache:insert({file, File}),
63-
{noreply}
64-
end.
65-
66-
handle_info(reload_crl_file, State = #state{socket = ListenSocket, port = Port,
67-
options = _Options, timer = TimerReference}) ->
68-
_ = erlang:cancel_timer(TimerReference, [{async, true}, {info, false}]),
69-
TRef = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), reload_clr_file),
70-
DefaultOptions = [binary, {packet, raw},
71-
{active, false}, {reuseaddr, true},
72-
{verify, verify_peer}, {depth, 1},
73-
{cacertfile, ca_cert_file()}, {certfile, cert_file()},
74-
{keyfile, key_file()}],
75-
NewOptions = handle_crl_check_options(DefaultOptions),
76-
ok = ssl:close(ListenSocket),
77-
{ok, NewSocket} = ssl:listen(Port, NewOptions),
78-
gen_server:cast(self(), accept),
79-
{noreply, State#state{socket = NewSocket, port = Port,
80-
options = NewOptions, timer = TRef}};
81-
handle_info(_Info, State) ->
82-
{noreply, State}.
83-
8457
terminate(_Reason, State) ->
85-
Timer = State#state.timer,
86-
_ = erlang:cancel_timer(Timer, [{async, true}, {info, false}]),
8758
ok.
8859

8960
handle_call(_E, _From, State) -> {noreply, State}.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
%%%-------------------------------------------------------------------
2+
%%% @doc
3+
%%%
4+
%%% Monitor module for reloading epp_tls_acceptor on runtime
5+
%%% Used to renew CRLs once in 30 minutes
6+
%%% @end
7+
%%% Created: 20 Feb 2020
8+
%%%-------------------------------------------------------------------
9+
-module(epp_tls_monitor).
10+
11+
-behaviour(gen_server).
12+
13+
-define(THIRTY_MINUTES_IN_MS, 30 * 60 * 1000).
14+
15+
-export([init/1, start_link/0]).
16+
17+
-export([code_change/3, handle_call/3, handle_cast/2,
18+
handle_info/2, terminate/2]).
19+
20+
-export([reload_acceptor/0]).
21+
22+
-record(state, {timer_ref :: timer:tref()}).
23+
24+
-type state() :: #state{}.
25+
26+
-spec start_link() -> ignore | {error, _} | {ok, pid()}.
27+
28+
start_link() ->
29+
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
30+
[]).
31+
32+
-spec init([]) -> {ok, state()}.
33+
34+
init([]) ->
35+
TimerReference = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), reload_acceptor),
36+
erlang:send(self(), reload_acceptor),
37+
{ok, #state{timer_ref = TimerReference}}.
38+
39+
%%%-------------------------------------------------------------------
40+
%%% GenServer callbacks
41+
%%%-------------------------------------------------------------------
42+
-spec handle_call(_, _, State) -> {stop,
43+
not_implemented, State}.
44+
45+
handle_call(_M, _F, State) ->
46+
{stop, not_implemented, State}.
47+
48+
-spec handle_cast(_, State) -> {stop, not_implemented,
49+
State}.
50+
51+
handle_cast(_M, State) ->
52+
{stop, not_implemented, State}.
53+
54+
-spec handle_info(reload_acceptor, _) -> {noreply, _}.
55+
56+
handle_info(reload_acceptor, State = #state{timer_ref = TimerReference}) ->
57+
_ = erlang:cancel_timer(TimerReference, [{async, true}, {info, false}]),
58+
TRef = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), reload_clr_file),
59+
ok = reload_acceptor(),
60+
{noreply, State#state{timer_ref = TRef}}.
61+
62+
-spec terminate(_, state()) -> ok.
63+
64+
terminate(_Reason, State) ->
65+
_ = erlang:cancel_timer(State#state.timer_ref, [{async, true}, {info, false}]),
66+
ok.
67+
68+
-spec code_change(_, _, _) -> {ok, _}.
69+
70+
code_change(_OldVersion, State, _Extra) -> {ok, State}.
71+
72+
%%%-------------------------------------------------------------------
73+
%%% Internal functions
74+
%%%-------------------------------------------------------------------
75+
reload_acceptor() ->
76+
supervisor:terminate_child(epp_proxy_sup, epp_tls_acceptor),
77+
supervisor:restart_child(epp_proxy_sup, epp_tls_acceptor),
78+
ok.

apps/epp_proxy/src/memory_monitor.erl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ start_link() ->
3434
-spec init([]) -> {ok, state()}.
3535

3636
init([]) ->
37-
{ok, TimerReference} =
38-
timer:send_interval(?THIRTY_MINUTES_IN_MS, log_usage),
37+
TimerReference = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), log_usage),
3938
erlang:send(self(), log_usage),
4039
{ok, #state{timer_ref = TimerReference}}.
4140

@@ -56,13 +55,17 @@ handle_cast(_M, State) ->
5655

5756
-spec handle_info(log_usage, _) -> {noreply, _}.
5857

59-
handle_info(log_usage, State) ->
60-
ok = log_memory(), {noreply, State}.
58+
handle_info(log_usage, State = #state{timer_ref = TimerReference}) ->
59+
_ = erlang:cancel_timer(TimerReference, [{async, true}, {info, false}]),
60+
TRef = erlang:send_after(?THIRTY_MINUTES_IN_MS, self(), reload_clr_file),
61+
ok = log_memory(),
62+
{noreply, State#state{timer_ref = TRef}}.
6163

6264
-spec terminate(_, state()) -> ok.
6365

6466
terminate(_Reason, State) ->
65-
{ok, cancel} = timer:cancel(State#state.timer_ref), ok.
67+
_ = erlang:cancel_timer(State#state.timer_ref, [{async, true}, {info, false}]),
68+
ok.
6669

6770
-spec code_change(_, _, _) -> {ok, _}.
6871

apps/epp_proxy/test/tls_client_SUITE.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ all() ->
3333
init_per_suite(Config) ->
3434
application:ensure_all_started(epp_proxy),
3535
application:ensure_all_started(hackney),
36+
ok = application:set_env(epp_proxy, crlfile_path, "test_ca/crl/first"),
3637
CWD = code:priv_dir(epp_proxy),
3738
Options = [binary,
3839
{certfile, filename:join(CWD, "test_ca/certs/client.crt.pem")},
@@ -121,14 +122,15 @@ session_test_case(Config) ->
121122
second_revoked_session_test_case(Config) ->
122123
ok = application:set_env(epp_proxy, crlfile_path, "test_ca/crl/second"),
123124

124-
epp_tls_acceptor ! reload_crl_file,
125+
epp_tls_monitor ! reload_acceptor,
125126

126127
Options = proplists:get_value(second_revoked_options, Config),
127128

128129
{error, Error} = ssl:connect("localhost", 1443, Options, 2000),
129130
{tls_alert,
130131
{certificate_revoked,
131132
"received CLIENT ALERT: Fatal - Certificate Revoked"}} = Error,
133+
%% "TLS client: In state cipher received SERVER ALERT: Fatal - Certificate Revoked\n "}} = Error,
132134
ok.
133135

134136
valid_command_test_case(Config) ->

config/test.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
{cacertfile_path, "test_ca/certs/ca.crt.pem"},
1313
{certfile_path, "test_ca/certs/apache.crt"},
1414
{keyfile_path, "test_ca/private/apache.key"},
15-
{crlfile_path, "test_ca/crl"}]},
15+
{crlfile_path, "test_ca/crl/first"}]},
1616

1717

1818
{lager, [

0 commit comments

Comments
 (0)