ACME TLS implementation using TLS-ALPN-01 - closes #160
This commit is contained in:
@@ -30,7 +30,7 @@ use hyper::{body::Bytes, Method, StatusCode};
|
||||
use jmap_proto::error::request::RequestError;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::JMAP;
|
||||
use crate::{services::housekeeper, JMAP};
|
||||
|
||||
use super::{http::ToHttpResponse, HttpRequest, JsonResponse};
|
||||
|
||||
@@ -299,6 +299,17 @@ impl JMAP {
|
||||
.into_http_response(),
|
||||
}
|
||||
}
|
||||
("certificates", Some("reload"), &Method::GET) => {
|
||||
let _ = self
|
||||
.housekeeper_tx
|
||||
.send(housekeeper::Event::ReloadCertificates)
|
||||
.await;
|
||||
|
||||
JsonResponse::new(json!({
|
||||
"data": [],
|
||||
}))
|
||||
.into_http_response()
|
||||
}
|
||||
(path_1 @ ("queue" | "report"), Some(path_2), &Method::GET) => {
|
||||
self.smtp
|
||||
.handle_manage_request(req.uri(), req.method(), path_1, path_2)
|
||||
|
||||
@@ -42,7 +42,7 @@ use tokio::{
|
||||
io::{AsyncRead, AsyncWrite},
|
||||
net::TcpStream,
|
||||
};
|
||||
use utils::listener::{ServerInstance, SessionData, SessionManager};
|
||||
use utils::listener::{ServerInstance, SessionData, SessionManager, TcpAcceptorResult};
|
||||
|
||||
use crate::{
|
||||
auth::{oauth::OAuthMetadata, AccessToken},
|
||||
@@ -291,40 +291,45 @@ pub async fn parse_jmap_request(
|
||||
}
|
||||
|
||||
impl SessionManager for JmapSessionManager {
|
||||
fn spawn(&self, session: SessionData<TcpStream>) {
|
||||
fn spawn(&self, mut session: SessionData<TcpStream>) {
|
||||
let jmap = self.inner.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Some(tls_acceptor) = &session.instance.tls_acceptor {
|
||||
let span = session.span;
|
||||
match tls_acceptor.accept(session.stream).await {
|
||||
Ok(stream) => {
|
||||
handle_request(
|
||||
jmap,
|
||||
SessionData {
|
||||
stream,
|
||||
local_ip: session.local_ip,
|
||||
remote_ip: session.remote_ip,
|
||||
remote_port: session.remote_port,
|
||||
span,
|
||||
in_flight: session.in_flight,
|
||||
instance: session.instance,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "error",
|
||||
"Failed to accept TLS connection: {}",
|
||||
err
|
||||
);
|
||||
match session.instance.acceptor.accept(session.stream).await {
|
||||
TcpAcceptorResult::Tls(accept) => {
|
||||
let span = session.span;
|
||||
match accept.await {
|
||||
Ok(stream) => {
|
||||
handle_request(
|
||||
jmap,
|
||||
SessionData {
|
||||
stream,
|
||||
local_ip: session.local_ip,
|
||||
remote_ip: session.remote_ip,
|
||||
remote_port: session.remote_port,
|
||||
span,
|
||||
in_flight: session.in_flight,
|
||||
instance: session.instance,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
context = "tls",
|
||||
event = "error",
|
||||
"Failed to accept TLS connection: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle_request(jmap, session).await;
|
||||
TcpAcceptorResult::Plain(stream) => {
|
||||
session.stream = stream;
|
||||
handle_request(jmap, session).await;
|
||||
}
|
||||
TcpAcceptorResult::Close => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ use tokio::sync::mpsc;
|
||||
use utils::{
|
||||
config::Rate,
|
||||
ipc::DeliveryEvent,
|
||||
listener::tls::Certificate,
|
||||
map::ttl_dashmap::{TtlDashMap, TtlMap},
|
||||
snowflake::SnowflakeIdGenerator,
|
||||
UnwrapFailure,
|
||||
@@ -186,6 +187,7 @@ impl JMAP {
|
||||
config: &utils::config::Config,
|
||||
stores: &Stores,
|
||||
directories: &Directories,
|
||||
certificates: Vec<Arc<Certificate>>,
|
||||
delivery_rx: mpsc::Receiver<DeliveryEvent>,
|
||||
smtp: Arc<SMTP>,
|
||||
) -> Result<Arc<Self>, String> {
|
||||
@@ -420,7 +422,7 @@ impl JMAP {
|
||||
spawn_state_manager(jmap_server.clone(), config, state_rx);
|
||||
|
||||
// Spawn housekeeper
|
||||
spawn_housekeeper(jmap_server.clone(), config, housekeeper_rx);
|
||||
spawn_housekeeper(jmap_server.clone(), config, certificates, housekeeper_rx);
|
||||
|
||||
Ok(jmap_server)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ use std::sync::Arc;
|
||||
use tokio::sync::mpsc;
|
||||
use utils::{
|
||||
config::{cron::SimpleCron, Config},
|
||||
listener::tls::Certificate,
|
||||
map::ttl_dashmap::TtlMap,
|
||||
UnwrapFailure,
|
||||
};
|
||||
@@ -36,6 +37,7 @@ use super::IPC_CHANNEL_BUFFER;
|
||||
|
||||
pub enum Event {
|
||||
PurgeSessions,
|
||||
ReloadCertificates,
|
||||
IndexStart,
|
||||
IndexDone,
|
||||
#[cfg(feature = "test_mode")]
|
||||
@@ -43,7 +45,12 @@ pub enum Event {
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub fn spawn_housekeeper(core: Arc<JMAP>, settings: &Config, mut rx: mpsc::Receiver<Event>) {
|
||||
pub fn spawn_housekeeper(
|
||||
core: Arc<JMAP>,
|
||||
settings: &Config,
|
||||
certificates: Vec<Arc<Certificate>>,
|
||||
mut rx: mpsc::Receiver<Event>,
|
||||
) {
|
||||
let purge_cache = settings
|
||||
.property_or_static::<SimpleCron>("jmap.session.purge.frequency", "15 * *")
|
||||
.failed("Initialize housekeeper");
|
||||
@@ -69,6 +76,32 @@ pub fn spawn_housekeeper(core: Arc<JMAP>, settings: &Config, mut rx: mpsc::Recei
|
||||
Event::PurgeSessions => {
|
||||
do_purge = true;
|
||||
}
|
||||
Event::ReloadCertificates => {
|
||||
let certificates = certificates.clone();
|
||||
tokio::spawn(async move {
|
||||
for cert in certificates {
|
||||
match cert.reload().await {
|
||||
Ok(_) => {
|
||||
tracing::info!(
|
||||
context = "tls",
|
||||
event = "reload",
|
||||
path = cert.path[0].to_string_lossy().as_ref(),
|
||||
"Reloaded certificate."
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
context = "tls",
|
||||
event = "error",
|
||||
path = cert.path[0].to_string_lossy().as_ref(),
|
||||
error = ?err,
|
||||
"Failed to reload certificate."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Event::IndexStart => {
|
||||
if !index_busy {
|
||||
index_busy = true;
|
||||
@@ -104,7 +137,9 @@ pub fn spawn_housekeeper(core: Arc<JMAP>, settings: &Config, mut rx: mpsc::Recei
|
||||
tracing::debug!("Housekeeper task exiting.");
|
||||
return;
|
||||
}
|
||||
Err(_) => (),
|
||||
Err(_) => {
|
||||
do_purge = true;
|
||||
}
|
||||
}
|
||||
|
||||
if do_purge {
|
||||
|
||||
Reference in New Issue
Block a user