1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use rustls::pki_types::PrivateKeyDer;
use rustls::ServerConfig;
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::path::PathBuf;
use std::{fs, fs::File, io::BufReader};

use crate::cli::TlsOptions;
use crate::error::{CertificateError, EdgeError};
use crate::types::EdgeResult;

pub(crate) fn build_upstream_certificate(
    upstream_certificate: Option<PathBuf>,
) -> EdgeResult<Option<reqwest::tls::Certificate>> {
    upstream_certificate
        .map(|cert| {
            fs::read(cert)
                .map_err(|e| {
                    EdgeError::ClientCertificateError(CertificateError::RootCertificatesError(
                        format!("{e:?}"),
                    ))
                })
                .and_then(|bytes| {
                    reqwest::Certificate::from_pem(&bytes).map_err(|e| {
                        EdgeError::ClientCertificateError(CertificateError::RootCertificatesError(
                            format!("{e:?}"),
                        ))
                    })
                })
                .map(Some)
        })
        .unwrap_or(Ok(None))
}

pub fn config(tls_config: TlsOptions) -> Result<ServerConfig, EdgeError> {
    let config = ServerConfig::builder().with_no_client_auth();
    let mut cert_file = BufReader::new(
        File::open(
            tls_config
                .tls_server_cert
                .expect("No TLS server cert")
                .as_path(),
        )
        .map_err(|_| EdgeError::TlsError)?,
    );
    let mut key_file = BufReader::new(
        File::open(tls_config.tls_server_key.expect("No server key").as_path())
            .expect("Could not read cert file"),
    );
    let cert_chain = certs(&mut cert_file).filter_map(|f| f.ok()).collect();
    let mut keys: Vec<PrivateKeyDer> = pkcs8_private_keys(&mut key_file)
        .filter_map(|f| f.map(PrivateKeyDer::from).ok())
        .collect();
    config
        .with_single_cert(cert_chain, keys.remove(0))
        .map_err(|_e| EdgeError::TlsError)
}