ws: reload tls config on SIGUSR1

This commit is contained in:
Joakim Frostegård 2023-10-24 18:36:56 +02:00
parent c5c995bb80
commit 6a23ef9103
8 changed files with 34 additions and 10 deletions

View file

@ -19,6 +19,7 @@
#### Added #### Added
* Add support for reporting peer client information * Add support for reporting peer client information
* Reload TLS certificate and key on SIGUSR1
#### Changed #### Changed

1
Cargo.lock generated
View file

@ -311,6 +311,7 @@ dependencies = [
"aquatic_peer_id", "aquatic_peer_id",
"aquatic_toml_config", "aquatic_toml_config",
"aquatic_ws_protocol", "aquatic_ws_protocol",
"arc-swap",
"async-tungstenite", "async-tungstenite",
"cfg-if", "cfg-if",
"futures", "futures",

View file

@ -30,6 +30,7 @@ aquatic_ws_protocol.workspace = true
anyhow = "1" anyhow = "1"
async-tungstenite = "0.23" async-tungstenite = "0.23"
arc-swap = "1"
cfg-if = "1" cfg-if = "1"
futures = "0.3" futures = "0.3"
futures-lite = "1" futures-lite = "1"

View file

@ -85,6 +85,11 @@ pub struct NetworkConfig {
pub tcp_backlog: i32, pub tcp_backlog: i32,
/// Enable TLS /// Enable TLS
///
/// 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 a successful update
/// results in emitting of an info-level log message.
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,

View file

@ -10,6 +10,7 @@ use aquatic_common::cpu_pinning::glommio::{get_worker_placement, set_affinity_fo
use aquatic_common::cpu_pinning::WorkerIndex; use aquatic_common::cpu_pinning::WorkerIndex;
use aquatic_common::rustls_config::create_rustls_config; use aquatic_common::rustls_config::create_rustls_config;
use aquatic_common::{PanicSentinelWatcher, ServerStartInstant}; use aquatic_common::{PanicSentinelWatcher, ServerStartInstant};
use arc_swap::ArcSwap;
use glommio::{channels::channel_mesh::MeshBuilder, prelude::*}; use glommio::{channels::channel_mesh::MeshBuilder, prelude::*};
use signal_hook::{ use signal_hook::{
consts::{SIGTERM, SIGUSR1}, consts::{SIGTERM, SIGUSR1},
@ -76,13 +77,13 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
let priv_dropper = PrivilegeDropper::new(config.privileges.clone(), config.socket_workers); let priv_dropper = PrivilegeDropper::new(config.privileges.clone(), config.socket_workers);
let opt_tls_config = if config.network.enable_tls { let opt_tls_config = if config.network.enable_tls {
Some(Arc::new( Some(Arc::new(ArcSwap::from_pointee(
create_rustls_config( 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,
) )
.with_context(|| "create rustls config")?, .with_context(|| "create rustls config")?,
)) )))
} else { } else {
None None
}; };
@ -181,6 +182,20 @@ 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);
if let Some(tls_config) = opt_tls_config.as_ref() {
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

@ -13,6 +13,7 @@ use aquatic_common::rustls_config::RustlsConfig;
use aquatic_common::{PanicSentinel, ServerStartInstant}; use aquatic_common::{PanicSentinel, ServerStartInstant};
use aquatic_peer_id::PeerClient; use aquatic_peer_id::PeerClient;
use aquatic_ws_protocol::*; use aquatic_ws_protocol::*;
use arc_swap::ArcSwap;
use async_tungstenite::WebSocketStream; use async_tungstenite::WebSocketStream;
use futures::stream::{SplitSink, SplitStream}; use futures::stream::{SplitSink, SplitStream};
use futures::{AsyncWriteExt, StreamExt}; use futures::{AsyncWriteExt, StreamExt};
@ -59,7 +60,7 @@ pub async fn run_socket_worker(
_sentinel: PanicSentinel, _sentinel: PanicSentinel,
config: Config, config: Config,
state: State, state: State,
opt_tls_config: Option<Arc<RustlsConfig>>, opt_tls_config: Option<Arc<ArcSwap<RustlsConfig>>>,
control_message_mesh_builder: MeshBuilder<SwarmControlMessage, Partial>, control_message_mesh_builder: MeshBuilder<SwarmControlMessage, Partial>,
in_message_mesh_builder: MeshBuilder<(InMessageMeta, InMessage), Partial>, in_message_mesh_builder: MeshBuilder<(InMessageMeta, InMessage), Partial>,
out_message_mesh_builder: MeshBuilder<(OutMessageMeta, OutMessage), Partial>, out_message_mesh_builder: MeshBuilder<(OutMessageMeta, OutMessage), Partial>,
@ -370,12 +371,12 @@ async fn run_connection(
server_start_instant: ServerStartInstant, server_start_instant: ServerStartInstant,
out_message_consumer_id: ConsumerId, out_message_consumer_id: ConsumerId,
connection_id: ConnectionId, connection_id: ConnectionId,
opt_tls_config: Option<Arc<RustlsConfig>>, opt_tls_config: Option<Arc<ArcSwap<RustlsConfig>>>,
ip_version: IpVersion, ip_version: IpVersion,
mut stream: TcpStream, mut stream: TcpStream,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
if let Some(tls_config) = opt_tls_config { if let Some(tls_config) = opt_tls_config {
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?;