Skip to main content

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}