feat(tls): add support for https in actix web (#5089)

Co-authored-by: noagbmn <>
This commit is contained in:
Noa
2024-07-01 15:35:40 +05:00
committed by GitHub
parent 4fbff39906
commit 2688d24d49
7 changed files with 158 additions and 9 deletions

View File

@ -12,6 +12,8 @@ impl Default for super::settings::Server {
host: "localhost".into(),
request_body_limit: 16 * 1024, // POST request body is limited to 16KiB
shutdown_timeout: 30,
#[cfg(feature = "tls")]
tls: None,
}
}
}

View File

@ -547,6 +547,8 @@ pub struct Server {
pub host: String,
pub request_body_limit: usize,
pub shutdown_timeout: u64,
#[cfg(feature = "tls")]
pub tls: Option<ServerTls>,
}
#[derive(Debug, Deserialize, Clone)]
@ -826,6 +828,19 @@ pub struct PayPalOnboarding {
pub enabled: bool,
}
#[cfg(feature = "tls")]
#[derive(Debug, Deserialize, Clone)]
pub struct ServerTls {
/// Port to host the TLS secure server on
pub port: u16,
/// Use a different host (optional) (defaults to the host provided in [`Server`] config)
pub host: Option<String>,
/// private key file path associated with TLS (path to the private key file (`pem` format))
pub private_key: PathBuf,
/// certificate file associated with TLS (path to the certificate file (`pem` format))
pub certificate: PathBuf,
}
fn deserialize_hashset_inner<T>(value: impl AsRef<str>) -> Result<HashSet<T>, String>
where
T: Eq + std::str::FromStr + std::hash::Hash,

View File

@ -200,11 +200,65 @@ pub async fn start_server(conf: settings::Settings<SecuredSecret>) -> Applicatio
);
let state = Box::pin(AppState::new(conf, tx, api_client)).await;
let request_body_limit = server.request_body_limit;
let server = actix_web::HttpServer::new(move || mk_app(state.clone(), request_body_limit))
.bind((server.host.as_str(), server.port))?
.workers(server.workers)
.shutdown_timeout(server.shutdown_timeout)
.run();
let server_builder =
actix_web::HttpServer::new(move || mk_app(state.clone(), request_body_limit))
.bind((server.host.as_str(), server.port))?
.workers(server.workers)
.shutdown_timeout(server.shutdown_timeout);
#[cfg(feature = "tls")]
let server = match server.tls {
None => server_builder.run(),
Some(tls_conf) => {
let cert_file =
&mut std::io::BufReader::new(std::fs::File::open(tls_conf.certificate).map_err(
|err| errors::ApplicationError::InvalidConfigurationValueError(err.to_string()),
)?);
let key_file =
&mut std::io::BufReader::new(std::fs::File::open(tls_conf.private_key).map_err(
|err| errors::ApplicationError::InvalidConfigurationValueError(err.to_string()),
)?);
let cert_chain = rustls_pemfile::certs(cert_file)
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
errors::ApplicationError::InvalidConfigurationValueError(err.to_string())
})?;
let mut keys = rustls_pemfile::pkcs8_private_keys(key_file)
.map(|key| key.map(rustls::pki_types::PrivateKeyDer::Pkcs8))
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
errors::ApplicationError::InvalidConfigurationValueError(err.to_string())
})?;
// exit if no keys could be parsed
if keys.is_empty() {
return Err(errors::ApplicationError::InvalidConfigurationValueError(
"Could not locate PKCS8 private keys.".into(),
));
}
let config_builder = rustls::ServerConfig::builder().with_no_client_auth();
let config = config_builder
.with_single_cert(cert_chain, keys.remove(0))
.map_err(|err| {
errors::ApplicationError::InvalidConfigurationValueError(err.to_string())
})?;
server_builder
.bind_rustls_0_22(
(tls_conf.host.unwrap_or(server.host).as_str(), tls_conf.port),
config,
)?
.run()
}
};
#[cfg(not(feature = "tls"))]
let server = server_builder.run();
let _task_handle = tokio::spawn(receiver_for_error(rx, server.handle()).in_current_span());
Ok(server)
}