From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id C0C707B0E2 for ; Tue, 11 May 2021 15:54:07 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B20C522CAB for ; Tue, 11 May 2021 15:54:07 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 62A4622C8D for ; Tue, 11 May 2021 15:54:05 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 3D40442BE6 for ; Tue, 11 May 2021 15:54:05 +0200 (CEST) From: Wolfgang Bumiller To: pbs-devel@lists.proxmox.com Date: Tue, 11 May 2021 15:53:58 +0200 Message-Id: <20210511135400.32406-6-w.bumiller@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210511135400.32406-1-w.bumiller@proxmox.com> References: <20210511135400.32406-1-w.bumiller@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.019 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [proxmox-backup-proxy.rs] Subject: [pbs-devel] [PATCH backup 5/7] proxy: implement 'reload-certificate' command X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 May 2021 13:54:07 -0000 to be used via the command socket Signed-off-by: Wolfgang Bumiller --- src/bin/proxmox-backup-proxy.rs | 62 ++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index c05bcd20..793ba67d 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -1,5 +1,6 @@ use std::sync::Arc; use std::path::{Path, PathBuf}; +use std::pin::Pin; use std::os::unix::io::AsRawFd; use anyhow::{bail, format_err, Error}; @@ -7,6 +8,7 @@ use futures::*; use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype}; use tokio_stream::wrappers::ReceiverStream; +use serde_json::Value; use proxmox::try_block; use proxmox::api::RpcEnvironmentType; @@ -119,13 +121,24 @@ async fn run() -> Result<(), Error> { // certificate! let acceptor = make_tls_acceptor()?; - let acceptor = Arc::new(acceptor.build()); + // to renew the acceptor we just let a command-socket handler trigger a Notify: + let notify_tls_cert_reload = Arc::new(tokio::sync::Notify::new()); + commando_sock.register_command( + "reload-certificate".to_string(), + { + let notify_tls_cert_reload = Arc::clone(¬ify_tls_cert_reload); + move |_value| -> Result<_, Error> { + notify_tls_cert_reload.notify_one(); + Ok(Value::Null) + } + }, + )?; let server = daemon::create_daemon( ([0,0,0,0,0,0,0,0], 8007).into(), - |listener, ready| { + move |listener, ready| { - let connections = accept_connections(listener, acceptor, debug); + let connections = accept_connections(listener, acceptor, debug, notify_tls_cert_reload); let connections = hyper::server::accept::from_stream(ReceiverStream::new(connections)); Ok(ready @@ -188,30 +201,61 @@ fn accept_connections( listener: tokio::net::TcpListener, acceptor: Arc, debug: bool, + notify_tls_cert_reload: Arc, ) -> tokio::sync::mpsc::Receiver { let (sender, receiver) = tokio::sync::mpsc::channel(MAX_PENDING_ACCEPTS); - tokio::spawn(accept_connection(listener, acceptor, debug, sender)); + tokio::spawn(accept_connection(listener, acceptor, debug, sender, notify_tls_cert_reload)); receiver } async fn accept_connection( listener: tokio::net::TcpListener, - acceptor: Arc, + mut acceptor: Arc, debug: bool, sender: tokio::sync::mpsc::Sender, + notify_tls_cert_reload: Arc, ) { let accept_counter = Arc::new(()); + // Note that these must not be moved out/modified directly, they get pinned in the loop and + // "rearmed" after waking up: + let mut reload_tls = notify_tls_cert_reload.notified(); + let mut accept = listener.accept(); + loop { - let (sock, _addr) = match listener.accept().await { - Ok(conn) => conn, - Err(err) => { - eprintln!("error accepting tcp connection: {}", err); + let sock; + + // normally we'd use `tokio::pin!()` but we need this to happen outside the loop and we + // need to be able to "rearm" the futures: + let reload_tls_pin = unsafe { Pin::new_unchecked(&mut reload_tls) }; + let accept_pin = unsafe { Pin::new_unchecked(&mut accept) }; + tokio::select! { + _ = reload_tls_pin => { + // rearm the notification: + reload_tls = notify_tls_cert_reload.notified(); + + log::info!("reloading certificate"); + match make_tls_acceptor() { + Err(err) => eprintln!("error reloading certificate: {}", err), + Ok(new_acceptor) => acceptor = new_acceptor, + } continue; } + res = accept_pin => match res { + Err(err) => { + eprintln!("error accepting tcp connection: {}", err); + continue; + } + Ok((new_sock, _addr)) => { + // rearm the accept future: + accept = listener.accept(); + + sock = new_sock; + } + } }; sock.set_nodelay(true).unwrap(); -- 2.20.1