http: reload tls config on SIGUSR1

This commit is contained in:
Joakim Frostegård 2023-10-24 18:44:49 +02:00
parent 6a23ef9103
commit 99647a323a
7 changed files with 37 additions and 8 deletions

View file

@ -14,12 +14,18 @@
* Add support for reporting peer client information * Add support for reporting peer client information
### aquatic_http
#### Added
* Reload TLS certificate (and key) on SIGUSR1
### aquatic_ws ### aquatic_ws
#### Added #### Added
* Add support for reporting peer client information * Add support for reporting peer client information
* Reload TLS certificate and key on SIGUSR1 * Reload TLS certificate (and key) on SIGUSR1
#### Changed #### Changed

1
Cargo.lock generated
View file

@ -118,6 +118,7 @@ dependencies = [
"aquatic_common", "aquatic_common",
"aquatic_http_protocol", "aquatic_http_protocol",
"aquatic_toml_config", "aquatic_toml_config",
"arc-swap",
"cfg-if", "cfg-if",
"either", "either",
"futures", "futures",

View file

@ -28,6 +28,7 @@ aquatic_http_protocol.workspace = true
aquatic_toml_config.workspace = true aquatic_toml_config.workspace = true
anyhow = "1" anyhow = "1"
arc-swap = "1"
cfg-if = "1" cfg-if = "1"
either = "1" either = "1"
futures = "0.3" futures = "0.3"

View file

@ -77,6 +77,12 @@ pub struct NetworkConfig {
/// Maximum number of pending TCP connections /// Maximum number of pending TCP connections
pub tcp_backlog: i32, pub tcp_backlog: i32,
/// Path to TLS certificate (DER-encoded X.509) /// Path to TLS certificate (DER-encoded X.509)
///
/// The TLS files are read on start and when the program receives `SIGUSR1`.
/// If initial parsing fails, the program exits. Later failures result in
/// in emitting of an error-level log message, while successful updates
/// result in emitting of an info-level log message. Updates only affect
/// new connections.
pub tls_certificate_path: PathBuf, pub tls_certificate_path: PathBuf,
/// Path to TLS private key (DER-encoded ASN.1 in PKCS#8 or PKCS#1 format) /// Path to TLS private key (DER-encoded ASN.1 in PKCS#8 or PKCS#1 format)
pub tls_private_key_path: PathBuf, pub tls_private_key_path: PathBuf,

View file

@ -9,6 +9,7 @@ use aquatic_common::{
rustls_config::create_rustls_config, rustls_config::create_rustls_config,
PanicSentinelWatcher, ServerStartInstant, PanicSentinelWatcher, ServerStartInstant,
}; };
use arc_swap::ArcSwap;
use common::State; use common::State;
use glommio::{channels::channel_mesh::MeshBuilder, prelude::*}; use glommio::{channels::channel_mesh::MeshBuilder, prelude::*};
use signal_hook::{ use signal_hook::{
@ -57,10 +58,10 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
let (sentinel_watcher, sentinel) = PanicSentinelWatcher::create_with_sentinel(); let (sentinel_watcher, sentinel) = PanicSentinelWatcher::create_with_sentinel();
let priv_dropper = PrivilegeDropper::new(config.privileges.clone(), config.socket_workers); let priv_dropper = PrivilegeDropper::new(config.privileges.clone(), config.socket_workers);
let tls_config = Arc::new(create_rustls_config( let tls_config = Arc::new(ArcSwap::from_pointee(create_rustls_config(
&config.network.tls_certificate_path, &config.network.tls_certificate_path,
&config.network.tls_private_key_path, &config.network.tls_private_key_path,
)?); )?));
let server_start_instant = ServerStartInstant::new(); let server_start_instant = ServerStartInstant::new();
@ -144,6 +145,18 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
match signal { match signal {
SIGUSR1 => { SIGUSR1 => {
let _ = update_access_list(&config.access_list, &state.access_list); let _ = update_access_list(&config.access_list, &state.access_list);
match create_rustls_config(
&config.network.tls_certificate_path,
&config.network.tls_private_key_path,
) {
Ok(config) => {
tls_config.store(Arc::new(config));
::log::info!("successfully updated tls config");
}
Err(err) => ::log::error!("could not update tls config: {:#}", err),
}
} }
SIGTERM => { SIGTERM => {
if sentinel_watcher.panic_was_triggered() { if sentinel_watcher.panic_was_triggered() {

View file

@ -15,6 +15,7 @@ use aquatic_http_protocol::request::{Request, RequestParseError, ScrapeRequest};
use aquatic_http_protocol::response::{ use aquatic_http_protocol::response::{
FailureResponse, Response, ScrapeResponse, ScrapeStatistics, FailureResponse, Response, ScrapeResponse, ScrapeStatistics,
}; };
use arc_swap::ArcSwap;
use either::Either; use either::Either;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt}; use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt};
@ -59,7 +60,7 @@ pub async fn run_socket_worker(
_sentinel: PanicSentinel, _sentinel: PanicSentinel,
config: Config, config: Config,
state: State, state: State,
tls_config: Arc<RustlsConfig>, tls_config: Arc<ArcSwap<RustlsConfig>>,
request_mesh_builder: MeshBuilder<ChannelRequest, Partial>, request_mesh_builder: MeshBuilder<ChannelRequest, Partial>,
priv_dropper: PrivilegeDropper, priv_dropper: PrivilegeDropper,
server_start_instant: ServerStartInstant, server_start_instant: ServerStartInstant,
@ -208,12 +209,12 @@ impl Connection {
request_senders: Rc<Senders<ChannelRequest>>, request_senders: Rc<Senders<ChannelRequest>>,
server_start_instant: ServerStartInstant, server_start_instant: ServerStartInstant,
connection_id: ConnectionId, connection_id: ConnectionId,
tls_config: Arc<RustlsConfig>, tls_config: Arc<ArcSwap<RustlsConfig>>,
connection_slab: Rc<RefCell<Slab<ConnectionReference>>>, connection_slab: Rc<RefCell<Slab<ConnectionReference>>>,
stream: TcpStream, stream: TcpStream,
peer_addr: CanonicalSocketAddr, peer_addr: CanonicalSocketAddr,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let tls_acceptor: TlsAcceptor = tls_config.into(); let tls_acceptor: TlsAcceptor = tls_config.load_full().into();
let stream = tls_acceptor.accept(stream).await?; let stream = tls_acceptor.accept(stream).await?;
let mut response_buffer = [0; RESPONSE_BUFFER_SIZE]; let mut response_buffer = [0; RESPONSE_BUFFER_SIZE];

View file

@ -88,8 +88,9 @@ pub struct NetworkConfig {
/// ///
/// The TLS files are read on start and when the program receives `SIGUSR1`. /// The TLS files are read on start and when the program receives `SIGUSR1`.
/// If initial parsing fails, the program exits. Later failures result in /// If initial parsing fails, the program exits. Later failures result in
/// in emitting of an error-level log message, while a successful update /// in emitting of an error-level log message, while successful updates
/// results in emitting of an info-level log message. /// result in emitting of an info-level log message. Updates only affect
/// new connections.
pub enable_tls: bool, pub enable_tls: bool,
/// Path to TLS certificate (DER-encoded X.509) /// Path to TLS certificate (DER-encoded X.509)
pub tls_certificate_path: PathBuf, pub tls_certificate_path: PathBuf,