actix_settings/settings/tls.rs
1use std::path::PathBuf;
2
3#[cfg(feature = "openssl")]
4use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
5#[cfg(feature = "rustls-0_23")]
6use rustls_0_23::{
7 pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer},
8 ServerConfig as Rustls023ServerConfig,
9};
10use serde::Deserialize;
11
12use crate::AsResult;
13
14/// TLS (HTTPS) configuration.
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
16#[serde(rename_all = "kebab-case")]
17#[doc(alias = "ssl", alias = "https")]
18pub struct Tls {
19 /// True if accepting TLS connections should be enabled.
20 pub enabled: bool,
21
22 /// Path to certificate `.pem` file.
23 pub certificate: PathBuf,
24
25 /// Path to private key `.pem` file.
26 pub private_key: PathBuf,
27}
28
29impl Tls {
30 /// Returns an [`SslAcceptorBuilder`] with the configured settings.
31 ///
32 /// The result is often used with [`actix_web::HttpServer::bind_openssl()`].
33 ///
34 /// # Example
35 ///
36 /// ```no_run
37 /// use std::io;
38 /// use actix_settings::{ApplySettings as _, Settings};
39 /// use actix_web::{get, web, App, HttpServer, Responder};
40 ///
41 /// #[actix_web::main]
42 /// async fn main() -> io::Result<()> {
43 /// let settings = Settings::from_default_template();
44 ///
45 /// HttpServer::new(|| {
46 /// App::new().route("/", web::to(|| async { "Hello, World!" }))
47 /// })
48 /// .try_apply_settings(&settings)?
49 /// .bind(("127.0.0.1", 8080))?
50 /// .bind_openssl(("127.0.0.1", 8443), settings.actix.tls.get_ssl_acceptor_builder()?)?
51 /// .run()
52 /// .await
53 /// }
54 /// ```
55 #[cfg(feature = "openssl")]
56 #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
57 pub fn get_ssl_acceptor_builder(&self) -> AsResult<SslAcceptorBuilder> {
58 let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
59 builder.set_certificate_chain_file(&self.certificate)?;
60 builder.set_private_key_file(&self.private_key, SslFiletype::PEM)?;
61 builder.check_private_key()?;
62
63 Ok(builder)
64 }
65
66 /// Returns a [`Rustls023ServerConfig`] with the configured settings.
67 ///
68 /// The result is often used with [`actix_web::HttpServer::bind_rustls_0_23()`].
69 ///
70 /// # Example
71 ///
72 /// ```no_run
73 /// use std::io;
74 /// use actix_settings::{ApplySettings as _, Settings};
75 /// use actix_web::{web, App, HttpServer};
76 ///
77 /// #[actix_web::main]
78 /// async fn main() -> io::Result<()> {
79 /// let settings = Settings::from_default_template();
80 ///
81 /// HttpServer::new(|| {
82 /// App::new().route("/", web::to(|| async { "Hello, World!" }))
83 /// })
84 /// .try_apply_settings(&settings)?
85 /// .bind_rustls_0_23(
86 /// ("127.0.0.1", 8443),
87 /// settings.actix.tls.get_rustls_0_23_server_config()?,
88 /// )?
89 /// .run()
90 /// .await
91 /// }
92 /// ```
93 #[cfg(feature = "rustls-0_23")]
94 #[cfg_attr(docsrs, doc(cfg(feature = "rustls-0_23")))]
95 pub fn get_rustls_0_23_server_config(&self) -> AsResult<Rustls023ServerConfig> {
96 let cert_chain = CertificateDer::pem_file_iter(&self.certificate)
97 .map_err(|err| crate::Error::RustlsError(err.to_string()))?
98 .collect::<Result<Vec<_>, _>>()
99 .map_err(|err| crate::Error::RustlsError(err.to_string()))?;
100 let private_key = PrivateKeyDer::from_pem_file(&self.private_key)
101 .map_err(|err| crate::Error::RustlsError(err.to_string()))?;
102
103 Ok(Rustls023ServerConfig::builder()
104 .with_no_client_auth()
105 .with_single_cert(cert_chain, private_key)?)
106 }
107}