rusty_api/core/
config.rs

1/*!
2 * The `config` module provides functionality for loading and configuring TLS settings for the API server.
3 *
4 * This module simplifies the process of setting up secure HTTPS communication by
5 * reading certificate and private key files and creating a `ServerConfig` object
6 * compatible with Rustls and Actix Web. This module is used internally by the `Api` struct.
7 *
8 * This module features:
9 * - **Certificate Loading**: Reads and parses PEM-encoded certificate chains.
10 * - **Private Key Loading**: Reads and parses PEM-encoded private keys.
11 * - **Rustls Integration**: Creates a `ServerConfig` for secure HTTPS communication.
12 *
13 * # Example
14 * ```rust,no_run
15 * use rusty_api::Api;
16 *
17 * let api = Api::new()
18 *    .certs("path/to/cert.pem", "path/to/key.pem") // Load the certificate and key into the API struct
19 *    .start(); // Starting the API server will call this module internally.
20 * ```
21 */
22use rustls::{pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject}, ServerConfig};
23use std::path::Path;
24
25/// Loads the TLS configuration for the API server.
26pub fn load_rustls_config(cert_path: impl AsRef<Path>, key_path: impl AsRef<Path>) -> Option<ServerConfig> {
27    let cert_path = cert_path.as_ref();
28    let key_path = key_path.as_ref();
29
30    // Load the certificate chain from the provided file
31    let cert_chain: Vec<CertificateDer> = match CertificateDer::pem_file_iter(cert_path)
32        .map(|res| res.flatten().collect::<Vec<_>>())
33    {
34        Ok(chain) if !chain.is_empty() => chain,
35        Ok(_) => {
36            println!("Error: No certificates found in {}", cert_path.display());
37            return None;
38        }
39        Err(e) => {
40            println!("Error: Failed to parse PEM file at {}: {}", cert_path.display(), e);
41            return None;
42        }
43    };
44
45    // Load the private key from the provided file
46    let key_der = match PrivateKeyDer::from_pem_file(key_path) {
47        Ok(key) => key,
48        Err(_) => {
49            println!("Error: No private key found in {}", key_path.display());
50            return None;
51        }
52    };
53
54    // Build and return the Rustls server configuration
55    match ServerConfig::builder()
56        .with_no_client_auth()
57        .with_single_cert(cert_chain, key_der)
58    {
59        Ok(config) => Some(config),
60        Err(e) => {
61            println!("Error: Failed to build TLS configuration: {}", e);
62            None
63        }
64    }
65}